我有一个哈希,它使用数组作为它的键。当我更改数组时,散列不再能获得相应的键和值:
1.9.3p194 :016 > a = [1, 2]
=> [1, 2]
1.9.3p194 :017 > b = { a => 1 }
=> {[1, 2]=>1}
1.9.3p194 :018 > b[a]
=> 1
1.9.3p194 :019 > a.delete_at(1)
=> 2
1.9.3p194 :020 > a
=> [1]
1.9.3p194 :021 > b
=> {[1]=>1}
1.9.3p194 :022 > b[a]
=> nil
1.9.3p194 :023 > b.keys.include? a
=> true
我做错了什么?
更新: OK。使用a.clone绝对是解决这个问题的一种方法。如果我想更改"a“,但仍然使用"a”来检索相应的值(因为"a“仍然是键之一),该怎么办?
发布于 2012-08-29 21:37:37
#rehash方法将重新计算散列,因此在键更改后执行以下操作:
b.rehash
发布于 2012-08-29 21:04:15
散列使用它们的键对象的散列码(a.hash
)对它们进行分组。散列代码通常依赖于对象的状态;在这种情况下,当从数组中删除一个元素时,a
的散列代码会发生变化。由于密钥已经被插入到散列中,因此a
被归档到其原始散列代码下。
这意味着您不能在b
中检索a
的值,即使在打印散列时看起来没有问题。
发布于 2012-08-29 19:44:03
您应该使用a.clone
作为密钥
irb --> a = [1, 2]
==> [1, 2]
irb --> b = { a.clone => 1 }
==> {[1, 2]=>1}
irb --> b[a]
==> 1
irb --> a.delete_at(1)
==> 2
irb --> a
==> [1]
irb --> b
==> {[1, 2]=>1} # STILL UNCHANGED
irb --> b[a]
==> nil # Trivial, since a has changed
irb --> b.keys.include? a
==> false # Trivial, since a has changed
使用a.clone
将确保即使我们稍后更改a
,密钥也是不变的。
https://stackoverflow.com/questions/12177074
复制相似问题