2012-02-12 7 views
1

に3つの並列の配列を結合するための最良かつ最速の方法です私は、たとえばOpenStructのために、複数のデータ要素を持つ単一のアレイにarrrays @a@b、および@cを結合したいと思います:ルビー

@a = ["my", "foo", "bar"] 
@b = ["yan", "can", "cook"] 
@c = ["in", "your", "dreams"] 

出力は次のようになります。

[ 
    { :a => "my", :b => "yan", :c => "in" }, 
    { :a => "foo", :b => "can", :c => "your" }, 
    { :a => bar, :b => "cook", :c => "dreams" } 
] 

これを行う最も簡単な方法は何ですか?私は別のクラスを検討する必要がありますか?

ここ
+0

あなたがOpenStruct' 'について何を意味するのですか?ハッシュの代わりに 'a'、' b'、 'c'属性を持つ' OpenStruct'オブジェクトの配列を取得したいですか? –

+0

通常、「最善の」解決策(より理解しやすく、よりモジュラー的な解決策)が最速ではないことに注意してください。 – tokland

+0

パフォーマンスはどうですか、最高のものは何ですか? – hagope

答えて

4

が一つの解決策ですが、私はそれがneatestでかなり納得していない午前:

@a.zip(@b, @c).map {|t| {:a => t[0], :b => t[1], :c => t[2]}} 
+3

私はここで構造化バインドを使用することを好むでしょう、私は通常それをはるかに読みやすく見つける: '@ a.zip(@b、@c).map {| a、b、c | simetryのために、{:a => a、:b => b、:c => c}} ' –

1

異なる長さの配列を心配する必要がない場合、私はそれを反復処理としてそれが最速の方法(だと思います配列回のみ):このような

@a.each_with_index.map { |a, i| { :a => a, :b => @b[i], :c => @c[i] } } 
+0

、私は次のように書くでしょう:' 3 | map {| i | {:a => @a [i]、:b => @b [i]、:c => @c [i]}} ' – tokland

0

何か作業をする必要があります:

(0 ... [@a, @b, @c].max_by(&:length).length).map { |i| { :a => @a[i], :b => @b[i], :c => @c[i] } } 

それは彼らがすべて同じ長さであると仮定しませんが、そうでなければnilの値を得ます。

3

機能アプローチ:

[@a, @b, @c].transpose.map { |xs| Hash[[:a, :b, :c].zip(xs)] } 
#=> [{:a=>"my", :b=>"yan", :c=>"in"}, {:a=>"foo", :b=>"can", :c=>"your"}, {:a=>"bar", :b=>"cook", :c=>"dreams"}] 
2

最速の方法を知るための最良の方法は、ベンチマークを行うことです。前の回答に基づいて:

require 'benchmark' 

@a = ["my", "foo", "bar"] 
@b = ["yan", "can", "cook"] 
@c = ["in", "your", "dreams"] 
$n = 500_000 

Benchmark.bmbm do |x| 
    x.report("Boris Strandjev") do $n.times do 
    @a.zip(@b, @c).map {|t| {:a => t[0], :b => t[1], :c => t[2]}} 
    end end 
    x.report("tokland") do $n.times do 
    [@a, @b, @c].transpose.map { |xs| Hash[[:a, :b, :c].zip(xs)] } 
    end end 
    x.report("mu is too short") do $n.times do 
    (0 ... [@a, @b, @c].max_by(&:length).length).map { |i| { :a => @a[i], :b => @b[i], :c => @c[i] } } 
    end end 
    x.report("KL-7") do $n.times do 
    @a.each_with_index.map { |a, i| { :a => a, :b => @b[i], :c => @c[i] } } 
    end end 
end 

出力:

Rehearsal --------------------------------------------------- 
Boris Strandjev 4.540000 0.015000 4.555000 ( 4.571261) 
tokland   7.145000 0.000000 7.145000 ( 7.268415) 
mu is too short 5.304000 0.047000 5.351000 ( 5.560318) 
KL-7    4.914000 0.000000 4.914000 ( 5.030287) 
----------------------------------------- total: 21.965000sec 

         user  system  total  real 
Boris Strandjev 4.462000 0.016000 4.478000 ( 4.553260) 
tokland   7.129000 0.031000 7.160000 ( 7.309418) 
mu is too short 5.366000 0.031000 5.397000 ( 5.447312) 
KL-7    4.898000 0.016000 4.914000 ( 4.997286) 
+0

これは非常に便利です。 – hagope