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 }
精彩评论