2011-07-08 219 views
4

我只會貼上一個簡單的例子,我試過了,這樣對讀者來說就很清楚了。紅寶石:哈希鍵的屬性

irb(main):001:0> h = { } 
=> {} 
irb(main):002:0> a=[1,2,3] 
=> [1, 2, 3] 
irb(main):003:0> a.object_id 
=> 69922343540500 


irb(main):004:0> h[a] = 12   #Hash with the array as a key 
=> 12 
irb(main):005:0> a << 4    #Modified the array 
=> [1, 2, 3, 4] 
irb(main):006:0> a.object_id  #Object id obviously remains the same. 
=> 69922343540500 
irb(main):007:0> h[a]    #Hash with the same object_id now returns nil. 
=> nil 
irb(main):008:0> h     #Modified hash 
=> {[1, 2, 3, 4]=>12} 
irb(main):009:0> h[[1,2,3,4]]  #Tried to access the value with the modified key - 
=> nil 


irb(main):011:0> h.each { |key,value| puts "#{key.inspect} maps #{value}" } 
[1, 2, 3, 4] maps 12 
=> {[1, 2, 3, 4]=>12} 

現在,當我遍歷散列,它可能識別鍵和值之間的映射。

有人可以解釋我這ruby哈希的行爲和什麼是散列鍵的屬性。

1)正如我上面提到的,object_id沒有改變 - 那麼爲什麼值設置爲零。

2)是否有任何可能的方式,以便我可以從哈希'h'取回值'12',因爲上面提到的h [[1,2,3,4]]返回nil。

回答

1

使用#eql?方法檢查散列密鑰,並且由於[1, 2, 3]不是.eql?[1, 2, 3,4]您的散列查找具有不同的結果。

也許你想使用除Array以外的東西作爲Hash鍵如果語義不適合你?

1

ruby hash api提供了答案:當密鑰用作密鑰時,密鑰的值不應改變。

我想實習生哈希計算爲a並用於快速查找(因爲密鑰不應該改變,散列總是相同的)。所以當你做h[a]時,它找不到匹配項([1,2,3] .hash!= [1,2,3,4] .hash),當你做h[[1,2,3]]哈希匹配,但對象不匹配([1,2,3]!= [1,2,3,4])。

修復方法是使用object_id作爲鍵,因爲它不會更改,h[a.object_id] = 12將在返回12時發生更改。 Ofcourse,這具有h[[1,2,3].object_id]不會回到12

1

斯特凡科爾曼的回答的缺點是比較徹底,但一些觀察:

紅寶石使用Object#散列法散列的對象。

您可以像在這時做a.delete(4); h[a]那樣退出12,[1,2,3]也可以再次用作關鍵。

8

發生這種情況的原因是密鑰在使用時不應更改其值。如果值發生變化,我們應該根據當前值重建散列。 rehash方法請看Ruby API。您可以通過在密鑰更改後重新生成哈希來獲取該值,如下所示:

irb(main):022:0> h.rehash 
=> {[1, 2, 3, 4]=>12} 
irb(main):023:0> h[a] 
=> 12