开发者

Add up values in hashes

array1 = { "d1" => 2, "d2" => 3}
array2 = { "d1" => 3, "d3" => 10}

i want this:

array3 = { "d1" => 5, "d2" => 3, "d3" => 10}

i tried this, it doesn't work. i am getting the error: "NoMethodError: undefined method `+' for nil:NilClass"

array3 = {}
array1.each {|key, count| array3[key] += count}
array2.each {|key, count| array3[key] += count开发者_如何学JAVA}


You're getting the error because array1.each tries to access array3['d1'], which doesn't exist yet, so it returns nil as the value. You just need to define array3 a bit more specifically, using Hash.new to tell it to assign 0 to all keys by default.

array3 = Hash.new(0)
array1.each {|key, count| array3[key] += count}
array2.each {|key, count| array3[key] += count}

Be careful going forward, though: the object you pass as the default value can be modified, so if you were to write my_hash = Hash.new(Array.new); my_hash[:some_key] << 3 then all keys that receive a default value will share the same object. This is one of those strange gotchas in Ruby, and you would want to use the block version of Hash.new in that case.


it is much more simplier

=> h1 = { "a" => 100, "b" => 200 }
{"a"=>100, "b"=>200}
=> h1 = { "a" => 100, "b" => 200 }
{"b"=>254, "c"=>300}
=> h1.merge(h2) {|key, oldval, newval| newval + oldval}
{"a"=>100, "b"=>454, "c"=>300}

it was undocumented in core-1.8.7 but you can read more here: http://www.ruby-doc.org/core/classes/Hash.src/M000759.html

it works on both versions


User you have to initialize the key for the non-existent values in the second array:

irb(main):007:0> array1 = {"d1" => 2, "d2" => 3}
=> {"d1"=>2, "d2"=>3}
irb(main):008:0> array2 = {"d1" => 3, "d3" => 10}
=> {"d1"=>3, "d3"=>10}
irb(main):009:0> array3 = {}
=> {}
irb(main):010:0> array1.each {|key, count| array3[key] = (array3[key] || 0) + count}
=> {"d1"=>2, "d2"=>3}
irb(main):011:0> array2.each {|key, count| array3[key] = (array3[key] || 0) + count}
=> {"d1"=>3, "d3"=>10}
irb(main):012:0> array3
=> {"d1"=>5, "d2"=>3, "d3"=>10}
irb(main):013:0> 


If all the keys in your hash are not integers you can use this trick which uses the fact that string.to_i gives zero

hash.to_a.flatten.inject{|sum, n| sum.to_s.to_i + n.to_s.to_i }
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜