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

时间:2019-08-02 05:31:27

标签: ruby

如何使用相同的键,值对合并数组中的哈希?我有以下数组,

arry = [{"id" => 1, "val1" => 123},
        {"id" => 2, "val1" => 234},
        {"id" => 1, "val2" => 321},
        {"id" => 1, "val3" => 445},
        {"id" => 3, "val3" => 334}]

想要获得

arry = [{"id" => 1, "val1" => 123, "val2" => 321, "val3" => 445},
        {"id" => 2, "val1" => 234},
        {"id" => 3, "val3" => 334}]

有没有办法做到这一点?尝试了几种方法,但到目前为止没有成功。

3 个答案:

答案 0 :(得分:7)

您发布的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}]

如果您的输入可能在相同的"id"(例如{"id" => 1, "val1" => 123}, {"id" => 1, "val1" => 456})中具有相同的键,则需要决定如何合并它们。无论如何,Hash#merge所在的区块将是您的朋友。

答案 1 :(得分:1)

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

请注意,values的接收者为:

{1=>{"id"=>1, "val1"=>123, "val2"=>321, "val3"=>445},
 2=>{"id"=>2, "val1"=>234},
 3=>{"id"=>3, "val3"=>334}} 

这使用Hash#update(也称为merge)的形式,它使用块{ |_,o,n| o.merge(n) }来确定要合并的两个哈希中存在的键的值。有关三个块变量的说明,请参见文档。 (我在第一个通用键上使用了下划线,以表示它在块计算中未使用。)

答案 2 :(得分:0)

这也应该起作用

arry.group_by { |a| a['id'] }.map{|_, ar| ar.reduce(:merge)}

这将返回

[{"id"=>1, "val1"=>123, "val2"=>321, "val3"=>445}, {"id"=>2, "val1"=>234}, {"id"=>3, "val3"=>334}]