简体   繁体   中英

Merge hashes with same key value pair inside array

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.

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.

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) } { |_,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.)

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}]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM