2016-10-17 7 views
0

の配列をマージI次の配列があります。ハッシュ

x = [ { a: [1,2] }, { a: [3,4] }, { a: [5,6] } ] 

をし、私は(他のオプションの中で)使用しようとしました

{ a: [[1,2], [3,4], [5,6]] } 

mergeを取得する必要があります:

x.each_with_object({}) do |a, b| 
    b.merge!(a) {|k, o, n| o.zip(n) } 
end 

残念ながら、私は結果の周りに余分な配列を取得します。

提案がありますか?

THANKS

+1

ウィル ':A'は常にハッシュで唯一の鍵となりますか? –

答えて

4
x.flat_map(&:to_a).group_by(&:first).map{ |k, v| [k, v.map(&:last)] }.to_h 
#=> [{:a=>[[1, 2], [3, 4], [5, 6]]}] 
+1

ご協力いただきありがとうございます。何がうまくいくの? – macsig

1

それは多分期待される結果を取得するための最も効率的な方法ではありませんが、あなたが最後に、

h = Hash.new([]) 
x.each { |hash| 
    hash.each { |key, values| 
    h[key] = h[key] + [values] 
    } 
} 

その方法を行うことができますh{:a=>[[1, 2], [3, 4], [5, 6]]}

+3

'h = Hash.new([])'はすべてのキーで同じ配列を使います。単一キーハッシュでも機能しますが、デフォルト値が変更可能な場合はブロックフォームを使用する必要があります。 – Stefan

+0

@Stefanブロックフォームはどういう意味ですか?さらに、同じ配列ではどういう意味ですか? h [1] = [1] 'と' h [2] = [2] '、' h [1] 'と' h [2] 'は完全に独立しています。 –

+2

私は 'h = Hash.new {| hash、key |ハッシュ[キー] = []} '。 'h [:a] << 1}を介して' h = Hash.new([]) 'を実行し、デフォルトの配列に追加すると' h [:b] 'も' [1] 'になります。同じ配列を参照してください。ブロック形式はこの問題を解決します。 – Stefan

1
key = x.first.first.first 
    #=> :a 
{ key=>x.map { |h| h[key] } } 
    #=> {:a=>[[1, 2], [3, 4], [5, 6]]} 
です

a = x.first 
    #=> {:a=>[1, 2]} 
b = a.first 
    #=> [:a, [1, 2]] 
b.first 
    #=> :a 

もう一つの方法:

a = x.map { |h| h.merge(h) { |_,v,_| [v] } } 
    #=> [{:a=>[[1, 2]]}, {:a=>[[3, 4]]}, {:a=>[[5, 6]]}] 
a.reduce { |t,h| t.merge(h) { |_,o,n| o+n } } 
    #=> {:a=>[[1, 2], [3, 4], [5, 6]]} 

両方の工程がマージされ、両方のハッシュに存在するキーの値を決定するためにブロックを使用するハッシュ#マージの形式を使用。詳細については、ドキュメントを参照してください。

次のようにこの2つのステップが一つに組み合わせることができる:

x.reduce { |t,h| t.merge(h.merge(h) { |_,v,_| [v] }) { |_,o,n| o+n } } 
    #=> {:a=>[1, 2, [3, 4], [5, 6]]} 
+0

キー(:a)は実行時にわかりません(b:または:c) – macsig

+0

私の編集をご覧ください。 –

+0

ハッシュリテラルを使用できます。つまり、{key => x.map {| h | h [key]}} ' – Stefan

関連する問題