合并Ruby中的哈希数组并计算相同的键

时间:2016-10-14 20:48:57

标签: ruby-on-rails ruby

我有一些这种格式的数据

[{
    "_id" => "20",
    "value" => 1
}, {
    "_id" => "19",
    "value" => 1
}, {
    "_id" => nil,
    "value" => 8
}, {
    "_id" => "27",
    "value" => 1
}, {
    "_id" => "25",
    "value" => 3
}, {
    "_id" => "28",
    "value" => 1
}]

我想将相同的值与“_id”键合并,并将“值”值相加。

欲望输出

[{
    "_id" => "20",
    "value" => 1
}, {
    "_id" => "19",
    "value" => 2
}, {
    "_id" => nil,
    "value" => 8
}, ...]

有一种优雅的方法可以做到这一点吗?

我尝试了两个循环,但我认为这不是最好的方法。

2 个答案:

答案 0 :(得分:5)

与Ruby中的大多数内容一样,访问Enumerable文档会调出group_by方法,该方法可以通过某些任意标准帮助将事物组合在一起。将它与能够得到总和的东西结合起来就可以得到:

    arinvch 
    JOIN ( 
        SELECT aritrsh.clineitem
        FROM aritrsh 
            JOIN icitemh ON
                aritrsh.citemno = icitemh.citemno
        WHERE icitemh.ctype = 'CRM'
        ) table2 ON 
        arinvch.ccustno = aritrsh.ccustno;

答案 1 :(得分:2)

arr = [{ "_id" => "20", "value" => 1 },
       { "_id" => "19", "value" => 1 },
       { "_id" =>  nil, "value" => 8 },
       { "_id" => "20", "value" => 1 },
       { "_id" => "25", "value" => 3 },
       { "_id" => "19", "value" => 1 },
      ]

h = arr.each_with_object(Hash.new(0)) { |g,h| h[g["_id"]] += g["value"] }
  #=> {"20"=>2, "19"=>2, nil=>8, "25"=>3}

如果您想要返回一个哈希数组,其中包含"_id"的唯一值并更新"value"的值,您可以先计算h以上,然后

arr.uniq { |g| g["_id"] }.map { |g| g.update("_id"=>h[g["_id"]]) }
  #=> [{"_id"=>"20", "value"=>2}, {"_id"=>" 19", "value"=>2},
  #    {"_id"=>nil, "value"=>8}, {"_id"=>"25", "value"=>3}]  

这会将Array#uniq方法与块Enumerable#mapHash#update(又名merge!)一起使用。

或者,您可以编写以下内容。

arr.each_with_object({}) { |g,h|
  h.update(g["_id"]=>g) { |_,o,n| o.merge("value"=>o["value"]+n["value"]) } }.values
  #=> [{"_id"=>"20", "value"=>2}, {"_id"=>" 19", "value"=>2},
  #    {"_id"=>nil, "value"=>8}, {"_id"=>"25", "value"=>3}]  

同样,我使用了Hash#update,但这次我使用了一个块来确定两个哈希中合并的键的值。另请参阅Enumerable#each_with_objectHash#merge。请注意,作为参数,(k=>v)({ k=>v })的缩写。