# Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. module Arrow class Array include Enumerable include GenericFilterable include GenericTakeable class << self def new(*args) _builder_class = builder_class return super if _builder_class.nil? return super unless _builder_class.buildable?(args) _builder_class.build(*args) end def builder_class builder_class_name = "#{name}Builder" return nil unless const_defined?(builder_class_name) const_get(builder_class_name) end end # @param i [Integer] # The index of the value to be gotten. # # You can specify negative index like for `::Array#[]`. # # @return [Object, nil] # The `i`-th value. # # `nil` for NULL value or out of range `i`. def [](i) i += length if i < 0 return nil if i < 0 or i >= length if null?(i) nil else get_value(i) end end # @param other [Arrow::Array] The array to be compared. # @param options [Arrow::EqualOptions, Hash] (nil) # The options to custom how to compare. # # @return [Boolean] # `true` if both of them have the same data, `false` otherwise. # # @since 5.0.0 def equal_array?(other, options=nil) equal_options(other, options) end def each return to_enum(__method__) unless block_given? length.times do |i| yield(self[i]) end end def reverse_each return to_enum(__method__) unless block_given? (length - 1).downto(0) do |i| yield(self[i]) end end def to_arrow self end alias_method :value_data_type_raw, :value_data_type def value_data_type @value_data_type ||= value_data_type_raw end def to_a values end alias_method :is_in_raw, :is_in def is_in(values) case values when ::Array if self.class.builder_class.buildable?([values]) values = self.class.new(values) else values = self.class.new(value_data_type, values) end is_in_raw(values) when ChunkedArray is_in_chunked_array(values) else is_in_raw(values) end end # @api private alias_method :concatenate_raw, :concatenate # Concatenates the given other arrays to the array. # # @param other_arrays [::Array, Arrow::Array] The arrays to be # concatenated. # # Each other array is processed by {#resolve} before they're # concatenated. # # @example Raw Ruby Array # array = Arrow::Int32Array.new([1]) # array.concatenate([2, 3], [4]) # => Arrow::Int32Array.new([1, 2, 3, 4]) # # @example Arrow::Array # array = Arrow::Int32Array.new([1]) # array.concatenate(Arrow::Int32Array.new([2, 3]), # Arrow::Int8Array.new([4])) # => Arrow::Int32Array.new([1, 2, 3, 4]) # # @since 4.0.0 def concatenate(*other_arrays) other_arrays = other_arrays.collect do |other_array| resolve(other_array) end concatenate_raw(other_arrays) end # Concatenates the given other array to the array. # # If you have multiple arrays to be concatenated, you should use # {#concatenate} to concatenate multiple arrays at once. # # @param other_array [::Array, Arrow::Array] The array to be concatenated. # # `@other_array` is processed by {#resolve} before it's # concatenated. # # @example Raw Ruby Array # Arrow::Int32Array.new([1]) + [2, 3] # => Arrow::Int32Array.new([1, 2, 3]) # # @example Arrow::Array # Arrow::Int32Array.new([1]) + # Arrow::Int32Array.new([2, 3]) # => Arrow::Int32Array.new([1, 2, 3]) # # @since 4.0.0 def +(other_array) concatenate(other_array) end # Ensures returning the same data type array from the given array. # # @return [Arrow::Array] # # @overload resolve(other_raw_array) # # @param other_raw_array [::Array] A raw Ruby Array. A new Arrow::Array # is built by `self.class.new`. # # @example Raw Ruby Array # int32_array = Arrow::Int32Array.new([1]) # other_array = int32_array.resolve([2, 3, 4]) # other_array # => Arrow::Int32Array.new([2, 3, 4]) # # @overload resolve(other_array) # # @param other_array [Arrow::Array] Another Arrow::Array. # # If the given other array is an same data type array of # `self`, the given other array is returned as-is. # # If the given other array isn't an same data type array of # `self`, the given other array is casted. # # @example Same data type # int32_array = Arrow::Int32Array.new([1]) # other_int32_array = Arrow::Int32Array.new([2, 3, 4]) # other_array = int32_array.resolve(other_int32_array) # other_array.object_id == other_int32_array.object_id # # @example Other data type # int32_array = Arrow::Int32Array.new([1]) # other_int8_array = Arrow::Int8Array.new([2, 3, 4]) # other_array = int32_array.resolve(other_int32_array) # other_array #=> Arrow::Int32Array.new([2, 3, 4]) # # @since 4.0.0 def resolve(other_array) if other_array.is_a?(::Array) builder_class = self.class.builder_class if builder_class.nil? message = "[array][resolve] can't build #{value_data_type} array " + "from raw Ruby Array" raise ArgumentError, message end if builder_class.buildable?([other_array]) other_array = builder_class.build(other_array) elsif builder_class.buildable?([value_data_type, other_array]) other_array = builder_class.build(value_data_type, other_array) else message = "[array][resolve] need to implement " + "a feature that building #{value_data_type} array " + "from raw Ruby Array" raise NotImpelemented, message end other_array elsif other_array.respond_to?(:value_data_type) return other_array if value_data_type == other_array.value_data_type other_array.cast(value_data_type) else message = "[array][resolve] can't build #{value_data_type} array: " + "#{other_array.inspect}" raise ArgumentError, message end end end end