2012-02-29 120 views
8

Ruby允許你定義的哈希值默認值:顯示哈希時,但修改默認不修改默認的哈希值

h=Hash.new(['alright']) 
h['meh'] # => ["alright"] 

值的分配出現了。 'bad'哪裏?

h['good']=['fine','dandy'] 
h['bad'].push('unhappy') 
h # => {"good"=>["fine", "dandy"]} 

'bad'顯示出來,如果我們明確要求。

h['bad'] # => ["alright", "unhappy"] 

爲什麼修改後的默認值在顯示散列時不顯示?

+0

合法的問題,但它可能是重複的。 – 2012-02-29 22:44:10

回答

11

哈希的默認值不像你期待的那樣工作。當你說h[k],過程是這樣的:

  1. 如果我們有一個k鍵,返回其值。
  2. 如果我們有一個默認值爲哈希,返回該默認值。
  3. 如果我們有一個提供默認值的塊,請執行該塊並返回其返回值。

請注意,(2)和(3)對於將k插入哈希值沒有任何意見。默認值實質上將h[k]這個:

h.has_key?(k) ? h[k] : the_default_value 

所以,簡單地訪問一個不存在的關鍵和獲取的默認值後面不會添加缺少的關鍵哈希值。

此外,形式的東西:

Hash.new([ ... ]) 
# or 
Hash.new({ ... }) 

幾乎總是一個錯誤,你將分享正是爲了相同的默認數組或哈希所有的默認值。例如,如果你這樣做:

h = Hash.new(['a']) 
h[:k].push('b') 

然後h[:i]h[:j],......都將返回['a', 'b'],這就是很少你想要什麼。

我認爲你正在尋找的block form of the default value

h = Hash.new { |h, k| h[k] = [ 'alright' ] } 

這將做兩件事情:

  1. 訪問一個不存在的鍵是鍵添加到哈希,這將有提供的數組作爲其值。
  2. 所有的默認值將是不同的對象,所以改變一個不會改變其餘的。
2

發生什麼事是你修改了散列的默認值,由push ing'不快樂'到h['bad']。你還沒有完成實際上是添加'壞'的哈希,這就是爲什麼它不顯示當你檢查h

所有您所提供的代碼後,我嘗試這樣做:

>> p h['bleh'] 
=> ["allright", "unhappy"] 

這當然建議,我認爲默認值已經改變。在回答你的問題:「爲什麼修改默認不顯示哈希時顯示?」,你將有一個元素添加進去,而不是僅僅對其進行訪問:

>> h['bleh'] # Doesn't add 'bleh' to the hash 
>> p h 
=> {"good"=>["fine", "dandy"]} # See, no extra values 

>> h['bleh'] = h.default # Does add a new key with the default value 
>> p h 
=> {"good"=>["fine", "dandy"], "bleh"=>["allright", "unhappy"]} 
+1

哇。我的立場完全糾正。但是現在我很難爲這是爲什麼。 []是一個散列對象的方法,它返回一個結果。爲什麼要發送推送更改默認散列?開始挖掘ruby源代碼的時間... – 2012-02-29 03:16:46

+0

明白了。哈希對象仍包含對正在更新的數組的引用。刪除我的答案。 :) – 2012-02-29 03:20:56

+1

我假設默認值是傳遞給哈希的構造函數的數組的引用。當你'推'到那個,你直接修改陣列,而不是創建一個副本。舉個簡單的例子:'h = Hash.new('hello'); h ['something'] <<'aaa';把h.default'放回'helloaaa' – 2012-02-29 03:22:47