简体   繁体   English

在数组中合并具有相同键值对的哈希

[英]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不是有效的红宝石数组(我在编辑中将其修复。)

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. 如果您的输入可能在相同的"id"具有相同的键(例如{"id" => 1, "val1" => 123}, {"id" => 1, "val1" => 456} ),您就是决定如何合并它们。 In any case, Hash#merge with a block would be your friend there. 无论如何,将Hash#merge与块一起成为您的朋友。

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: 请注意, values的接收者为:

{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) }Hash#update (也称为merge )形式。 { |_,o,n| o.merge(n) } to determine the values of keys that are present in both hashes being merged. { |_,o,n| o.merge(n) }来确定合并的两个哈希中存在的键的值。 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}]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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