Ruby配列の特定のインデックスにある要素をプッシュします
概要
データベースから返される配列の配列があり、それらが常に同じ長さであることを確認したいと考えています。そうでない場合は、ゼロをプッシュして適切な長さにしつつ、インデックスの整合性も維持したいと考えています。
ほとんどの場合、次のようになります
array = [["apple", "blueberries", "banana", "kiwi"], ["20.15", "13.50", "22.10", "10.50"], ["10", "12", "26", "34"]]
最終的には each_with_index を呼び出して、それらを一致させる必要があります。表のリンゴ、20.15、10。
場合によっては、配列から 1 つまたは 2 つの要素が欠落している可能性があり、その場所に 0 をプッシュしたいことがあります。
array2 = [["apple", "blueberries", "banana", "kiwi"], ["20.15", "22.10"], ["10", "12", "26", "34"]]
私は次のようなことを試しました
array2.each {|f| f.push(0) until f.length === 4}
=>[["apple", "blueberries", "banana", "kiwi"], ["20.15", "13.50", 0, 0], ["10", "12", "26", "34"]]
ただし、ゼロは配列の最後にプッシュされます。理想的には、出力は次のようになります。
=>[["apple", "blueberries", "banana", "kiwi"], ["20.15", 0, "13.50", 0], ["10", "12", "26", "34"]]
解決策
あまり言いたくありませんが、プログラマーではない大人が時々想像するように、プログラミングは子供にとって簡単な仕事ではありません。あなたのケースでは、別のクラス、おそらく Array のサブクラスの作成が必要です。このような:
class GreenGrocer < Array
end
ここで、次のように GreenGrocer.new パブリック クラス メソッドを再定義して、各 GreenGrocer インスタンスに欠落している要素がゼロでパッチされていることを確認することを想像できます。
class GreenGrocer # reopening the class we defined earlier
class << self
def new array
produce, float_array, int_array = array.reduce( &:zip ).map( &:flatten ).transpose
super [ produce, float_array.map { |e| e or 0.0 }, int_array.map { |e| e or 0 } ]
end
def [] *elements; new elements end
end
end
# so we can call
g = GreenGrocer.new( array2 )
# or
g = GreenGrocer[ *array2 ]
しかし、なぜわざわざ?不完全なデータ構造を必要に応じてテーブルに変換し、その過程で欠落しているデータ ポイントをゼロで埋める #to_table メソッドを作成するだけで十分です。そこで次のように定義します。
class LazierGreenGrocer < Array
def to_table
reduce( &:zip ).map( &:flatten ).map { |e| e.map { |e| e || 0 } }
end
end
lazier_g = LazierGreenGrocer.new( array2 ) # not eager to do work upon initialization
lazier_g.to_table # does the required work as #to_table is called
これが私ならどうするかです。出力したいテーブルの正確な種類がわからないので、それに応じて #to_table メソッドを変更する必要があるかもしれません。