按键进行散列并对值进行求和
我有一个哈希数组:
[{"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