2016-09-08 8 views
0

:ありherehereのように、この程度のSOには、いくつかの同様の質問があったが、どれもかなり私が探しているもののように思えません。重複するキーを持つハッシュの配列をネストされたハッシュに「減らす」方法

は、私はこのようなハッシュの配列を持っていると言う:

arr_with_dup_hsh_keys = [ 
    { foo: "dup", bar: 1 }, 
    { foo: "dup", bar: 2 }, 
    { foo: "dup", bar: 3 }, 
    { foo: "dup", bar: 4 }, 
    { foo: "dup", bar: 5 } 
] 

私はこれにそれをダウン減らすにはどうすればよいですか? fooに異なる値が存在する場合

{ foo: "dup", bars: [1, 2, 3, 4, 5] } 

そして、何?

arr_with_dup_hsh_keys = [ 
    { foo: "dup", bar: 1 }, 
    { foo: "dup", bar: 2 }, 
    { foo: "soup", bar: 3 }, 
    { foo: "dup", bar: 4 }, 
    { foo: "soup", bar: 5 } 
] 
+0

は、あなたが何かをしようとしたことがありますか? –

+0

はい、私は 'group_by'と' inject'を使って複数の試行を試みましたが、達成しようとしているものの近くにはどこもありませんでした。 – binarymason

+3

'{foo:" dup "、bars:arr_with_dup_hsh_keys.map {| hsh | hsh [:bar]}} 'を実行します。 –

答えて

2
def combine(arr) 
    arr.group_by {|g|g[:foo]}.values.map {|a|{foo: a.first[:foo], bar: a.map {|g| g[:bar]}}} 
end 

combine arr_with_dup_hsh_keys 
    #=> [{:foo=>"dup", :bar=>[1, 2, 3, 4, 5]}] 

arr_with_dup_hsh_keys1 = [ 
    { foo: "dup", bar: 1 }, 
    { foo: "dup", bar: 2 }, 
    { foo: "soup", bar: 3 }, 
    { foo: "dup", bar: 4 }, 
    { foo: "soup", bar: 5 } 
] 

combine arr_with_dup_hsh_keys1 
    #=> [{:foo=>"dup", :bar=>[1, 2, 4]}, {:foo=>"soup", :bar=>[3, 5]}] 

Enumerable#group_byを参照してくださいと注意し

arr_with_dup_hsh_keys1.group_by { |g| g[:foo] } 
#=> {"dup"=> [{:foo=>"dup", :bar=>1}, {:foo=>"dup", :bar=>2}, 
#    {:foo=>"dup", :bar=>4}], 
# "soup"=>[{:foo=>"soup", :bar=>3}, {:foo=>"soup", :bar=>5}]} 

つまりあなたは可能性があり代わりに次のように記述します。

def combine(arr) 
    arr.each_with_object({}) do |g,h| 
    f = g.merge(bar: [g[:bar]]) 
    h.update(f[:foo]=>f) { |_,o,n| { foo: o[:foo], bar: o[:bar]+n[:bar] } } 
    end.values 
end 

combine arr_with_dup_hsh_keys1 
    #=> [{:foo=>"dup", :bar=>[1, 2, 4]}, {:foo=>"soup", :bar=>[3, 5]}] 

これは、マージされ、両方のハッシュに存在するキーの値を決定するためにブロックを使用(別名merge!Hash#updateの形態を使用します。 3つのブロック変数の説明については、ドキュメントを参照してください(最初は共通キーですが、ブロック計算で使用されていないことを示すためにアンダースコアで表しています)。

+0

これは私が必要としていたものです。 'foo'が' bar'や 'soup'のときに区別する必要があることを知ったに違いありません。ありがとうございました! – binarymason

+0

「mindmeld」と呼ばれることもあります。 –

+0

私は最初に 'group_by'を使い始めましたが、もう1つの配列レベルを作成したので問題がありました。どのように 'group_by'を使ってメソッドを続けるのですか? (あなたが気にしない場合) – binarymason

1

あなたのデータは本当にあなたの問題のように単純である場合、これはあなたがやりたいだろうが。

{ foo: "dup", 
    bars: arr_with_dup_hsh_keys.map {|hsh| hsh[:bar] } 
} 
+0

データはそれほど単純ではありません。ある範囲の値を持つ数百の 'foo'を持つことができ、それらの多くは上記の例のように重複しています。 – binarymason

1

これは私が思いついたものです:

a = [ 
    { foo: "dup", bar: 1 }, 
    { foo: "dup", bar: 2 }, 
    { foo: "dup", bar: 3 }, 
    { foo: "dup", bar: 4 }, 
    { foo: "dup", bar: 5 } 
] 

h = {} 
a.map(&:keys).uniq.flatten.each_with_index do |key, idx| 
    h[key] = a.map(&:values).collect { |a| a[idx]}.uniq 
end 
h 
#=> {:foo=>["dup"], :bar=>[1, 2, 3, 4, 5]} 
関連する問題