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

发布于 2024-10-07 23:28:37 字数 939 浏览 5 评论 0原文

我有一个哈希数组:

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

I have an array of hashes:

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

I need to use inject here I think but I've really been struggling.

I want a new hash that reflects the sum of the previous hash's duplicate keys:

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

I'm in control of the code that outputs this hash so I can modify it if necessary. The results were mainly hashes because this could end up nested any number of levels deep and then it's easy to call flatten on the array but not flatten the keys/values of the hash too:

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 

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

我最亲爱的 2024-10-14 23:28:38

只需使用:

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

Simply use:

array = [{"Vegetable"=>10}, {"Vegetable"=>5}, {"Dry Goods"=>3}, {"Dry Goods"=>2}]
array.inject{|a,b| a.merge(b){|_,x,y| x + y}}
北城半夏 2024-10-14 23:28:38
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}

如果您将 Hash.new 与默认值 0:

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}
ar = [{"Vegetable"=>10}, {"Vegetable"=>5}, {"Dry Goods"=>3}, {"Dry Goods"=>2}]

While the Hash.merge technique works fine, I think it reads better with an inject:

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

Better yet, if you use Hash.new with a default value of 0:

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

Or if inject makes your head hurt:

result = Hash.new(0)
ar.each { |subhash| subhash.each { |prod, value| result[prod] += value } }
result
=> {"Dry Goods"=>5, "Vegetable"=>15}
梦晓ヶ微光ヅ倾城 2024-10-14 23:28:38

我不确定这里的哈希是您想要的,因为我不在每个哈希中包含多个条目。所以我将从稍微改变你的数据表示开始。

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

现在使用facet gem,如下所示

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

结果是

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

I'm not sure that a hash is what you want here, because I don't multiple entries in each hash. so I'll start by changing your data representation a little.

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

If the hashes can have multiple key-value pairs, then what you probably want to do is

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

Now use the facets gem as follows

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

The result is

{"Dry Goods"=>5, "Vegetable"=>15}
冷血 2024-10-14 23:28:38

如果有两个具有多个键的哈希值:

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

If have two hashes with multiple keys:

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
千紇 2024-10-14 23:28:37
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 在发现重复项时运行该块;没有初始 memoinject 将数组的第一个元素视为 memo,这在这里很好。

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 runs the block when it finds a duplicate; inject without a initial memo treats the first element of the array as memo, which is fine here.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文