lib/arrow/array-builder.rb in red-arrow-0.15.1 vs lib/arrow/array-builder.rb in red-arrow-0.16.0
- old
+ new
@@ -24,71 +24,120 @@
if self != ArrayBuilder
builder = new
return builder.build(values)
end
- builder_class = nil
- builder_class_arguments = []
+ builder_info = nil
values.each do |value|
- case value
- when nil
- # Ignore
- when true, false
- return BooleanArray.new(values)
- when String
- return StringArray.new(values)
- when Float
- return DoubleArray.new(values)
- when Integer
- if value < 0
- builder = IntArrayBuilder.new
- return builder.build(values)
- else
- builder_class = UIntArrayBuilder
- builder_class_arguments = []
- end
- when Time
- data_type = value.data_type
- case data_type.unit
- when TimeUnit::SECOND
- if builder.nil?
- builder = Time32ArrayBuilder
- builder_class_arguments = [data_type]
- end
- when TimeUnit::MILLI
- if builder != Time64ArrayBuilder
- builder = Time32ArrayBuilder
- builder_class_arguments = [data_type]
- end
- when TimeUnit::MICRO
- builder = Time64ArrayBuilder
- builder_class_arguments = [data_type]
- when TimeUnit::NANO
- builder = Time64ArrayBuilder.new(data_type)
- return builder.build(values)
- end
- when ::Time
- data_type = TimestampDataType.new(:nano)
- builder = TimestampArrayBuilder.new(data_type)
- return builder.build(values)
- when DateTime
- return Date64Array.new(values)
- when Date
- return Date32Array.new(values)
- else
- return StringArray.new(values)
- end
+ builder_info = detect_builder_info(value, builder_info)
+ break if builder_info and builder_info[:detected]
end
- if builder_class
- builder = builder_class.new(*builder_class_arguments)
+ if builder_info
+ builder = builder_info[:builder]
builder.build(values)
else
Arrow::StringArray.new(values)
end
end
def buildable?(args)
args.size == method(:build).arity
+ end
+
+ private
+ def detect_builder_info(value, builder_info)
+ case value
+ when nil
+ builder_info
+ when true, false
+ {
+ builder: BooleanArrayBuilder.new,
+ detected: true,
+ }
+ when String
+ {
+ builder: StringArrayBuilder.new,
+ detected: true,
+ }
+ when Float
+ {
+ builder: DoubleArrayBuilder.new,
+ detected: true,
+ }
+ when Integer
+ if value < 0
+ {
+ builder: IntArrayBuilder.new,
+ detected: true,
+ }
+ else
+ {
+ builder: UIntArrayBuilder.new,
+ }
+ end
+ when Time
+ data_type = value.data_type
+ case data_type.unit
+ when TimeUnit::SECOND
+ builder_info || {
+ builder: Time32ArrayBuilder.new(data_type)
+ }
+ when TimeUnit::MILLI
+ if builder_info and builder_info[:builder].is_a?(Time64ArrayBuilder)
+ builder_info
+ else
+ {
+ builder: Time32ArrayBuilder.new(data_type),
+ }
+ end
+ when TimeUnit::MICRO
+ {
+ builder: Time64ArrayBuilder.new(data_type),
+ }
+ when TimeUnit::NANO
+ {
+ builder: Time64ArrayBuilder.new(data_type),
+ detected: true
+ }
+ end
+ when ::Time
+ data_type = TimestampDataType.new(:nano)
+ {
+ builder: TimestampArrayBuilder.new(data_type),
+ detected: true,
+ }
+ when DateTime
+ {
+ builder: Date64ArrayBuilder.new,
+ detected: true,
+ }
+ when Date
+ {
+ builder: Date32ArrayBuilder.new,
+ detected: true,
+ }
+ when ::Array
+ sub_builder_info = nil
+ value.each do |sub_value|
+ sub_builder_info = detect_builder_info(sub_value, sub_builder_info)
+ break if sub_builder_info and sub_builder_info[:detected]
+ end
+ if sub_builder_info and sub_builder_info[:detected]
+ sub_value_data_type = sub_builder_info[:builder].value_data_type
+ field = Field.new("item", sub_value_data_type)
+ {
+ builder: ListArrayBuilder.new(ListDataType.new(field)),
+ detected: true,
+ }
+ else
+ builder_info
+ end
+ else
+ {
+ builder: StringArrayBuilder.new,
+ detected: true,
+ }
+ end
end
end
def build(values)
append(*values)