Reputation: 13
How to merge hashes within array with same key, value pair? I have following array,
arry = [{"id" => 1, "val1" => 123},
{"id" => 2, "val1" => 234},
{"id" => 1, "val2" => 321},
{"id" => 1, "val3" => 445},
{"id" => 3, "val3" => 334}]
Want to get
arry = [{"id" => 1, "val1" => 123, "val2" => 321, "val3" => 445},
{"id" => 2, "val1" => 234},
{"id" => 3, "val3" => 334}]
is there ruby way to do it? Tried few ways but no success so far.
Upvotes: 0
Views: 425
Reputation: 121
This should work too,
arry.group_by { |a| a['id'] }.map{|_, ar| ar.reduce(:merge)}
This would return,
[{"id"=>1, "val1"=>123, "val2"=>321, "val3"=>445}, {"id"=>2, "val1"=>234}, {"id"=>3, "val3"=>334}]
Upvotes: 0
Reputation: 110645
arry.each_with_object({}) { |g,h| h.update(g["id"]=>g) { |_,o,n| o.merge(n) } }.values
#=> [{"id"=>1, "val1"=>123, "val2"=>321, "val3"=>445},
# {"id"=>2, "val1"=>234},
# {"id"=>3, "val3"=>334}]
Note the receiver of values
is:
{1=>{"id"=>1, "val1"=>123, "val2"=>321, "val3"=>445},
2=>{"id"=>2, "val1"=>234},
3=>{"id"=>3, "val3"=>334}}
This uses the form of Hash#update (aka merge
) that employs the block { |_,o,n| o.merge(n) }
to determine the values of keys that are present in both hashes being merged. See the doc for descriptions of the three block variables. (I've used an underscore for the first, the common key, to signify that it is not used in the block calculation.)
Upvotes: 1
Reputation: 120990
The arry
you have posted is not a valid ruby array in the first place (I fixed it in my edit.)
arry.
group_by { |h| h["id"] }.
values.
map { |a| a.reduce(&:merge) }
#⇒ [{"id"=>1, "val1"=>123, "val2"=>321, "val3"=>445},
# {"id"=>2, "val1"=>234}, {"id"=>3, "val3"=>334}]
If your input might have same keys within the same "id"
(like {"id" => 1, "val1" => 123}, {"id" => 1, "val1" => 456}
,) you are to decide how to merge them. In any case, Hash#merge
with a block would be your friend there.
Upvotes: 7