在哈希中查找数组特定值的总和

  • 本文关键字:哈希中 查找 数组 ruby
  • 更新时间 :
  • 英文 :


这是我的数组:

collection
=> [{:title=>"Movie A", :studio=>"Alpha Films", :worldwide_gross=>10},
{:title=>"Movie B", :studio=>"Alpha Films", :worldwide_gross=>30},
{:title=>"Movie C", :studio=>"Omega Films", :worldwide_gross=>30}]

我的目标是返回每个工作室的总和:

#=> :studio => "Alpha Films", :worldwide_gross => 40
#=> :studio => "Omega Films", :worldwide_gross => 30

到目前为止,我已经提出了以下逻辑,但它只一次性返回所有工作室的总和:

gross_result = collection.sum {|h| h[:worldwide_gross]}
result #=> 70

您可以使用Enumerable#group_byHash#transform_values然后像以前一样求和:

collection.group_by { |h| h[:studio] }.transform_values { |v| v.sum{ |h| h[:worldwide_gross] } }
#=> {"Alpha Films"=>40, "Omega Films"=>30}

group_by返回的位置:

collection.group_by { |h| h[:studio] }
#=> {"Alpha Films"=>[{:title=>"Movie A", :studio=>"Alpha Films", :worldwide_gross=>10}, {:title=>"Movie B", :studio=>"Alpha Films", :worldwide_gross=>30}], "Omega Films"=>[{:title=>"Movie C", :studio=>"Omega Films", :worldwide_gross=>30}]}

此解决方案首先创建一个哈希,其键是collectiong的所有哈希值的g[:studio]的唯一值,其值是给定键的所有gg[:worldwide_gross]的总和。然后将该哈希转换为所需的哈希。

collection.each_with_object(Hash.new(0)) do |g,h|  
h[g[:studio]] += g[:worldwide_gross]
end.map { |k,v| { studio: k, worldwide_gross: v } }
#=> [{:studio=>"Alpha Films", :worldwide_gross=>40},
#    {:studio=>"Omega Films", :worldwide_gross=>30}] 

这两个步骤如下。

h = collection.each_with_object(Hash.new(0)) do |g,h|
h[g[:studio]] += g[:worldwide_gross]
end
#=> {"Alpha Films"=>40, "Omega Films"=>30} 
h.map { |k,v| { studio: k, worldwide_gross: v } }
#=> [{:studio=>"Alpha Films", :worldwide_gross=>40},
#    {:studio=>"Omega Films", :worldwide_gross=>30}]  

h的计算(有时称为计数哈希)采用 Hash::new 的形式,它定义了一个默认值(此处为零),该默认值h[k]为哈希返回的值,h在没有键k时如此定义h。它等效于以下内容。

h = collection.each_with_object({}) do |g,h|
h[g[:studio]] = (h[g[:studio]] || 0) + g[:worldwide_gross]
end

如果h没有密钥g[:studio]h[g[:studio]] #=> nil,所以h[g[:studio]] || 0 #=> 0。如果h有一个键g[:studio](其值不是nilfalse),则h[g[:studio]] || 0 #=> h[g[:studio]]

您可以使用reduce方法

result = a.group_by { |h| h[:studio] }.values.map do |arr|
arr.reduce do |h1, h2|
h1.merge(h2) do |k, v1, v2|
k.eql?(:worldwide_gross) ? (v1 + v2) : v1
end
end
end

p 结果

[{:partner_name=>"company 1", :partner_id=>787, :value=>3}, {:partner_name=>"company 2", :partner_id=>768, :value=>1}, {:partner_name=>"company 3", :partner_id=>769, :value=>1}]

最新更新