2011-02-16 67 views
2
array1 = { "d1" => 2, "d2" => 3} 
array2 = { "d1" => 3, "d3" => 10} 

我想这一点:
array3 = { "d1" => 5, "d2" => 3, "d3" => 10}加起来值哈希

我想这一点,这是行不通的。我得到的错误:“NoMethodError:未定义的方法`+”的零:NilClass”

array3 = {} 
array1.each {|key, count| array3[key] += count} 
array2.each {|key, count| array3[key] += count} 
+1

如果您关注的是简洁,你可以改变这:`array3 = array1.merge(array2){| _,v1,v2 | v1 + v2}` – harbichidian 2011-02-16 02:53:14

回答

4

你得到的错误,因为array1.each试图访问array3['d1'],这还不存在,所以它返回值为nil。您只需要更具体地定义array3,使用Hash.new来指示它将0默认分配给所有密钥。

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

小心前进,但:你传递作为默认值的对象可以被修改,所以,如果你写my_hash = Hash.new(Array.new); my_hash[:some_key] << 3然后接收默认所有键价值将共享相同的对象。这是Ruby中那些奇怪的陷阱之一,在这种情况下,您会想要使用块版本Hash.new

+0

唯一的区别是“array3 = Hash.new 0”与“array3 = {}”,为什么你的版本工作,我的没有。 – user612308 2011-02-16 02:39:34

+0

`{}`与'Hash.new()`相同,但是`Hash.new`可以采用一个“默认值”,在这种情况下为0,可以指定任何尚未给出的键的值一个值呢。 – harbichidian 2011-02-16 02:41:48

+0

有道理,谢谢。如果我想初始化array3中的一个元素到一个特定的值,其余的为0,我可以在一行而不是2吗? `array3 = Hash.new 0 array3 [“d5”] = 12` – user612308 2011-02-16 02:56:29

1

用户,你必须初始化第二阵列中不存在的价值的关键:

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> 
2

它更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} 

它在核心1.8.7无证但你可以在这里阅读更多: http://www.ruby-doc.org/core/classes/Hash.src/M000759.html

它适用于这两个版本

0

如果所有的在你的散列是整数你可以使用这一招,它使用的事实,string.to_i给出零

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