2010-12-10 61 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 }