【问题标题】:Ruby: Properties of a hash keyRuby:哈希键的属性
【发布时间】:2011-07-08 08:30:53
【问题描述】:

我将粘贴一个我尝试过的简单示例,以便阅读本文的人清楚。

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 没有改变 - 那么为什么将值设置为 nil。

2) 有什么方法可以让我从哈希“h”中取回值“12”,因为上面提到的 h[[1,2,3,4]] 返回 nil。

【问题讨论】:

    标签: ruby


    【解决方案1】:

    发生这种情况是因为密钥在使用时不应更改其值。如果值发生变化,我们应该根据其当前值重建散列。查看Ruby APIrehash 方法。您可以通过在更改键后再次重建哈希来取回值,如下所示:

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

    【讨论】:

      【解决方案2】:

      使用#eql? 方法检查哈希键,由于[1, 2, 3] 不是.eql?[1, 2, 3,4],因此您的哈希查找有不同的结果。

      如果语义不适合你,也许你想使用 Array 以外的东西作为你的 Hash 键?

      【讨论】:

        【解决方案3】:

        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。当然,这有一个缺点,h[[1,2,3].object_id] 不会返回 12。

        【讨论】:

          【解决方案4】:

          Stefaan Colman 的回答更彻底,但有几点观察:

          Ruby 使用 Object#hash 方法来散列对象。

          此时你可以通过a.delete(4); h[a] 取出12,[1,2,3] 也可以再次用作密钥。

          【讨论】:

            猜你喜欢
            • 2012-01-02
            • 2011-07-01
            • 2019-04-24
            • 2013-08-18
            • 2011-06-30
            • 1970-01-01
            • 2011-03-16
            • 2018-03-01
            • 1970-01-01
            相关资源
            最近更新 更多