ruby中嵌套数组中的散列键总和

时间:2015-03-08 22:42:52

标签: ruby-on-rails ruby arrays ruby-on-rails-4 hash

我有一个包含具有相同键集的哈希数组的数组。我需要为每个数组求和每组键,给我留下一个哈希数组。

array = [
  [{"x"=>"Apr, 2014", "price_rate"=>10, "cost_rate"=>10, "profit"=>10},
   {"x"=>"May, 2014", "price_rate"=>10, "cost_rate"=>10, "profit"=>10},
   {"x"=>"Jun, 2014", "price_rate"=>10, "cost_rate"=>10, "profit"=>10} ],
  [{"x"=>"Apr, 2014", "price_rate"=>10, "cost_rate"=>10, "profit"=>10},
   {"x"=>"May, 2014", "price_rate"=>10, "cost_rate"=>10, "profit"=>10},
   {"x"=>"Jun, 2014", "price_rate"=>10, "cost_rate"=>10, "profit"=>10} ],
  [{"x"=>"Apr, 2014", "price_rate"=>10, "cost_rate"=>10, "profit"=>10},
   {"x"=>"May, 2014", "price_rate"=>10, "cost_rate"=>10, "profit"=>10},
   {"x"=>"Jun, 2014", "price_rate"=>10, "cost_rate"=>10, "profit"=>10} ]
]

哪会留下我

[{"x"=>"Apr, 2014", "price_rate"=>30, "cost_rate"=>30, "profit"=>30},
 {"x"=>"May, 2014", "price_rate"=>30, "cost_rate"=>30, "profit"=>30},
 {"x"=>"Jun, 2014", "price_rate"=>30, "cost_rate"=>30, "profit"=>30} ]

我已经尝试将它们拼合成一个单独的数组,合并(这似乎永远不会给我我期望的结果),并减少添加 - 但我无处可去。

有简洁的方法吗?

修改 另外值得注意的是,每个阵列中的散列数可以变化。这个例子是一年四分之一,但最终的解决方案应该是不可知的,以允许数据集提供的条目数量。

2 个答案:

答案 0 :(得分:3)

这是一种(纯Ruby)方式,它使用Hash#update(aka merge!)的形式,它使用块来确定合并的两个哈希中存在的键的值:

array.flatten.each_with_object({}) { |g,h|
  h.update(g["x"]=>g.dup) { |_,oh,nh|
    oh.update(nh) { |k,ov,nv| (k=="x") ? ov : ov+nv } } }.values
  #=> [{"x"=>"Apr, 2014", "price_rate"=>30, "cost_rate"=>30, "profit"=>30},
  #    {"x"=>"May, 2014", "price_rate"=>30, "cost_rate"=>30, "profit"=>30},
  #    {"x"=>"Jun, 2014", "price_rate"=>30, "cost_rate"=>30, "profit"=>30}]

trh指出我的原始解决方案修改了array,我错过了。为避免这种情况,我将g["x"]=>g更改为g["x"]=>g.dup

答案 1 :(得分:1)

以递归方式使用deep_merge。要使用2个哈希来执行此操作:

hash1.deep_merge(hash2) { |key, first, last| key == 'x' ? first : first + last }

这样做是合并每个键值,第一列除外(应始终匹配)。如果你遍历所有数组,你应该能够使用类似的策略将它们合并为一个。

更多信息:http://api.rubyonrails.org/classes/Hash.html#method-i-deep_merge