2010-12-10 64 views
31

初始化一个哈希里的数组我试图初始化数组这样的哈希作为我怎么能在Ruby中

@my_hash = Hash.new(Array.new) 

,这样我可以:

@my_hash["hello"].push("in the street") 
=> ["in the street"] 
@my_hash["hello"].push("at home") 
=> ["in the street", "at home"] 
@my_hash["hello"] 
=>["in the street", "at home"] 

的问题是,任何新散列键还返回["in the street", "at home"]

@my_hash["bye"] 
=> ["in the street", "at home"] 
@my_hash["xxx"] 
=> ["in the street", "at home"] 

!!! ???

我在做什么错误什么是正确的方法来初始化一个数组哈希?

+0

相关:http://stackoverflow.com/questions/190740/setting-ruby-hash-default-to-a-list – tokland 2010-12-10 15:38:51

回答

83
@my_hash = Hash.new(Array.new) 

这将创建只有一个数组对象,它返回的每一个关键是没有找到时间。既然你只是改变了那个数组,并且从来没有创建一个新的数组,所有的键映射到同一个数组。

你想要做的是:

@my_hash = Hash.new {|h,k| h[k] = Array.new } 

或者干脆

@my_hash = Hash.new {|h,k| h[k] = [] } 

传递一个块Hash.new不同于简单地传递一个参数在2种方式:

  1. 的每次找不到密钥时都会执行块。因此,你每次都会得到一个新的数组。在带有参数的版本中,该参数会被评估一次(在调用new之前),并且每次都会返回该结果。

  2. 通过做h[k] =你实际上将密钥插入散列。如果你不这样做,只访问@my_hash[some_key]实际上不会导致some_key被插入到散列中。

+14

的有一个问题需要注意的是在这里,现在连*检查*一键会创建它,这可能不是你想要的。因为这个原因,我有时候会创建Hash(仅仅是{}),然后在调用中创建数组,比如'(@myhash [“hello”] || = [])。push(“in the street “)'。 – 2010-12-10 16:32:41

2

Hash.new的参数是新散列键的默认值,所以当你传递一个引用时,引用将用于新的散列键。您要更新,当你调用参考...

hash["key"].push "value" 

你需要推值之前通过新的参考到哈希键...

hash["key1"] = Array.new 
hash["key1"].push "value1" 
hash["key2"] = Array.new 
hash["key2"].push "value2 

你可以试试这个封装也成为辅助方法。

7

试试这个:

@my_hash = Hash.new { |h, k| h[k] = Array.new }