我有一系列哈希,键是国家,值是天数。
我想在哈希值上进行汇总,并对相同国家/地区的值进行求和。
数组看起来像countries = [{"Country"=>"Brazil", "Duration"=>731/1 days}, {"Country"=>"Brazil", "Duration"=>365/1 days}]
我希望这可以返回以下内容:[{"Country" => "Brazil", "Duration"=>1096/1 days}]
我在SO like this one
上尝试了其他问题countries.inject{|new_h, old_h| new_h.merge(old_h) {|_, old_v, new_v| old_v + new_v}}
制作{"Country"=>"BrazilBrazil", "Duration"=>1096/1 days}
有没有办法有选择地只合并特定的值?
答案 0 :(得分:4)
这使用Hash::new的形式创建一个带有默认值的空哈希(此处为0
)。对于以这种方式创建的哈希h
,如果哈希没有键h[k]
,k
将返回默认值。哈希未被修改。
countries = [{"Country"=>"Brazil", "Duration"=>"731/1 days"},
{"Country"=>"Argentina", "Duration"=>"123/1 days"},
{"Country"=>"Brazil", "Duration"=>"240/1 days"},
{"Country"=>"Argentina", "Duration"=>"260/1 days"}]
countries.each_with_object(Hash.new(0)) {|g,h| h[g["Country"]] += g["Duration"].to_i }.
map { |k,v| { "Country"=>k, "Duration"=>"#{v}/1 days" } }
#=> [{"Country"=>"Brazil", "Duration"=>"971/1 days"},
# {"Country"=>"Argentina", "Duration"=>"383/1 days"}]
第一个散列传递给块并分配给块变量g
。
g = {"Country"=>"Brazil", "Duration"=>"731/1 days"}
此时h #=> {}
。然后我们计算
h[g["Country"]] += g["Duration"].to_i
#=> h["Brazil"] += "971/1 days".to_i
#=> h["Brazil"] = h["Brazil"] + 971
#=> h["Brazil"] = 0 + 971 # h["Brazil"]
有关"971/1 days".to_i
返回971
的原因的说明,请参阅String#to_i。
h["Brazil"]
返回默认值0
,因为h
尚未(还)有一个键"Brazil"
。请注意,右侧的h["Brazil"]
是h.[]("Brazil")
的语法糖,而左侧是h.[]=(h["Brazil"] + 97)
的语法糖。当散列没有给定键时,它返回默认值Hash#[]。其余步骤类似。
答案 1 :(得分:2)
您可以按如下方式更新您的代码:
countries.inject do |new_h, old_h|
new_h.merge(old_h) do |k, old_v, new_v|
if k=="Country" then old_v else old_v + new_v end
end
end
# => {"Country"=>"Brazil", "Duration"=>1096}
您基本上使用k
(用于键)参数来切换不同的合并策略。