简体   繁体   English

红宝石嵌套数组中哈希键的总和

[英]Sum of hash keys in nested array in ruby

I have an array containing arrays of hashes with identical sets of keys. 我有一个包含具有相同键集的哈希数组的数组。 I need to sum each set of keys for each array, leaving me with a single array of hashes. 我需要对每个数组的每个键集求和,只剩下一个哈希数组。

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

Which would leave me with 那会留给我

[{"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} ]

I've tried flattening them into a single array, merging (which never seems to give me the results I would expect), and reduce to add - but I'm getting nowhere. 我尝试将它们展平为单个数组,合并(这似乎从未给我带来我期望的结果),并减少添加-但我无济于事。

Is there a concise way to do this? 有一种简洁的方法吗?

EDIT Also of note is that the number of hashes in each array can vary. 编辑还要注意的是,每个数组中的哈希数可以变化。 The example was for a quarter of a year, but the resulting solution should be agnostic enough to allow for as many or as few entries as the data set provides. 该示例使用了一年的四分之一,但是生成的解决方案应该是不可知的,以允许输入或输入的数据集与数据集一样少。

This is one (pure Ruby) way, which uses the form of Hash#update (aka merge! ) that uses a block to determine the values of keys present in both hashes being merged: 这是一种(纯Ruby)方式,它使用Hash#update (也称为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 pointed out that my original solution modified array , which I had missed. trh指出我原来的解决方案修改了我错过的array To avoid that, I changed g["x"]=>g to g["x"]=>g.dup . 为了避免这种情况,我将g["x"]=>g更改为g["x"]=>g.dup

Look into using deep_merge recursively. 探究以递归方式使用deep_merge。 To do this with 2 hashes you would use: 为此,您可以使用2个散列:

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

What this is doing is merging each key value, except the first column (which should always match). 这是在合并每个键值,除了第一列(应始终匹配)。 If you loop through all your arrays youy should be able to merge them into one using a similar strategy. 如果遍历所有数组,则应该可以使用类似的策略将它们合并为一个数组。

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

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

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