按键对哈希进行分组并对值求和

Posted

技术标签:

【中文标题】按键对哈希进行分组并对值求和【英文标题】:Group hashes by keys and sum the values 【发布时间】:2011-05-26 02:35:14 【问题描述】:

我有一个哈希数组:

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

我想我需要在这里使用inject,但我真的很挣扎。

我想要一个新的哈希值,它反映了前一个哈希值的重复键的总和:

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

我控制着输出此哈希的代码,因此我可以在必要时对其进行修改。结果主要是散列,因为这最终可能会嵌套任意数量的深度,然后在数组上调用 flatten 很容易,但也不会展平散列的键/值:

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 

【问题讨论】:

见***.com/q/4091487/322020 【参考方案1】:
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 with a block 在找到重复时运行该块;没有初始memoinject 将数组的第一个元素视为memo,这在这里很好。

【讨论】:

谢谢,这回答了问题,我不知道合并。非常感谢。 +1 这是 Ruby 书籍中必须包含的珠宝之一,但不是。 能不能解释一下这里的命名,memo和el是什么意思? @appleLover memoel 没有任何意义,你可以用任何词来交换它们。它们是变量名;我为memo =>I remember, el => element选择了这些@ 你能帮我理解这段代码吗,请提及 k、old_v、new_v 的值。我很困惑【参考方案2】:

简单使用:

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

【讨论】:

感谢您为未使用的变量使用下划线 _【参考方案3】:
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

【讨论】:

名副其实的丰富建议【参考方案4】:

我不确定哈希是否是您想要的,因为我在每个哈希中没有多个条目。所以我先稍微改变一下你的数据表示。

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

【讨论】:

谢谢!我知道但需要真正弄脏的结构,我完全不知道各个方面。我添加了输出哈希的原始代码,因为我可能可以在那里做一些更简单的事情。【参考方案5】:

如果有两个带有多个键的哈希:

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

【讨论】:

以上是关于按键对哈希进行分组并对值求和的主要内容,如果未能解决你的问题,请参考以下文章

我如何在熊猫中分组然后对值求和? [复制]

Scala:如何按键分组并在 scala 中对值求和并以预期的返回类型返回列表

根据 pandas 中的字典对数据帧的行进行分组并对相应的分子求和

Pandas Dataframe - 按照Col A分组并对每个组进行求和[C]重复

使用数组中的键迭代哈希,并对结果求和

如何在 XSLT 中对值进行分组和求和