按键进行散列并对值进行求和

我有一个哈希数组:

[{"Vegetable"=>10}, {"Vegetable"=>5}, {"Dry Goods"=>3>}, {"Dry Goods"=>2}] 

我想在这里使用inject ,但是我一直在挣扎。

我想要一个新的散列,它反映了以前散列的重复键的总和:

 [{"Vegetable"=>15}, {"Dry Goods"=>5}] 

我在控制输出这个散列的代码,所以我可以修改它,如果有必要。 结果主要是散列,因为这可能最终嵌套任意数量的层次,然后很容易在数组上调用flatten,但是也不能将hash的键/值弄平:

 def recipe_pl(parent_percentage=nil) ingredients.collect do |i| recipe_total = i.recipe.recipeable.total_cost recipe_percentage = i.ingredient_cost / recipe_total if i.ingredientable.is_a?(Purchaseitem) if parent_percentage.nil? {i.ingredientable.plclass => recipe_percentage} else sub_percentage = recipe_percentage * parent_percentage {i.ingredientable.plclass => sub_percentage} end else i.ingredientable.recipe_pl(recipe_percentage) end end end 
 ar = [{"Vegetable"=>10}, {"Vegetable"=>5}, {"Dry Goods"=>3}, {"Dry Goods"=>2}] p ar.inject{|memo, el| memo.merge( el ){|k, old_v, new_v| old_v + new_v}} #=> {"Vegetable"=>15, "Dry Goods"=>5} 

带有块的Hash.merge在发现重复时运行该块; inject没有最初的memo对待数组的第一个元素作为memo ,在这里很好。

 ar = [{"Vegetable"=>10}, {"Vegetable"=>5}, {"Dry Goods"=>3}, {"Dry Goods"=>2}] 

虽然Hash.merge技术可以正常工作,但我认为使用inject技术会更好:

 ar.inject({}) { |memo, subhash| subhash.each { |prod, value| memo[prod] ||= 0 ; memo[prod] += value } ; memo } => {"Dry Goods"=>5, "Vegetable"=>15} 

更好的是,如果你使用默认值为0的Hash.new

 ar.inject(Hash.new(0)) { |memo, subhash| subhash.each { |prod, value| memo[prod] += value } ; memo } => {"Dry Goods"=>5, "Vegetable"=>15} 

或者如果inject使你头部受伤:

 result = Hash.new(0) ar.each { |subhash| subhash.each { |prod, value| result[prod] += value } } result => {"Dry Goods"=>5, "Vegetable"=>15} 

只需使用:

 array = [{"Vegetable"=>10}, {"Vegetable"=>5}, {"Dry Goods"=>3}, {"Dry Goods"=>2}] array.inject{|a,b| a.merge(b){|_,x,y| x + y}} 

我不确定在这里你想要的散列是什么,因为我不在每个散列多个条目。 所以我将从稍微改变你的数据表示开始。

 ProductCount=Struct.new(:name,:count) data = [ProductCount.new("Vegetable",10), ProductCount.new("Vegetable",5), ProductCount.new("Dry Goods",3), ProductCount.new("Dry Goods",2)] 

如果哈希可以有多个键值对,那么你可能想要做的是

 data = [{"Vegetable"=>10}, {"Vegetable"=>5}, {"Dry Goods"=>3>}, {"Dry Goods"=>2}] data = data.map{|h| h.map{|k,v| ProductCount.new(k,v)}}.flatten 

现在使用facets gem如下

 require 'facets' data.group_by(&:name).update_values{|x| x.map(&:count).sum} 

结果是

 {"Dry Goods"=>5, "Vegetable"=>15} 

如果有多个密钥的两个哈希值:

 h1 = { "Vegetable" => 10, "Dry Goods" => 2 } h2 = { "Dry Goods" => 3, "Vegetable" => 5 } details = {} (h1.keys | h2.keys).each do |key| details[key] = h1[key].to_i + h2[key].to_i end details