1

我首先运行了下面的第一部分代码并获得了所需的输出,现在只是为了解决它并做一些我在第二部分所做的研究。

第一部分

irb(main):001:0> h1 = { "a" => 100, "b" => 200, :c => "c" }
=> {"a"=>100, "b"=>200, :c=>"c"}
irb(main):002:0> h1["a"]
=> 100
irb(main):002:0> h1[:c]
=> "c"

第二部分

irb(main):003:0> h1.compare_by_identity
=> {"a"=>100, "b"=>200, :c=>"c"}
irb(main):004:0> h1.compare_by_identity?
=> true
irb(main):005:0> h1["a"]
=> nil
irb(main):006:0> h1[:c]
=> "c"
irb(main):007:0>

如何h1["a"]在第一部分和第二部分给出不同的值但不一样h1[:c]

我正在使用 Ruby 1.9.3。

4

1 回答 1

14

文档是compare_by_identity这样说的:

通过它们的身份hsh比较它的键,即它会将完全相同的对象视为相同的键。

通常,哈希键将使用 匹配eql?,但compare_by_identity将使用匹配它们equal?(这大致相当于比较object_ids*)。由于具有相同值的字符串的不同实例具有不同object_id的 s,因此它不匹配。但是,符号始终具有相同的object_id,因此它会继续匹配。

hash = { 'a' => 'str a', 'b' => 'str b', :c => 'sym c' }
hash.compare_by_identity

hash.keys.map(&:object_id)      #=> [70179407935200, 70179407935180, 358408]
['a', 'b', :c].map(&:object_id) #=> [70179405705480, 70179405705460, 358408]

hash.keys.zip(['a', 'b', :c]).map { |pair| pair.inject(:eql?) }   #=> [true, true, true]
hash.keys.zip(['a', 'b', :c]).map { |pair| pair.inject(:equal?) } #=> [false, false, true]

a_key = hash.keys.first  #=> 'a'
hash['a']   #=> nil
hash[a_key] #=> 'str a'
hash[:c]    #=> 'sym c'

如您所见,object_id字符串的 s 与散列中键的 s 不匹配object_id,但符号匹配。事实上,如果你反复运行'a'.object_id& 'b'.object_id(或调用object_id任何字符串),你每次都会得到不同的值。

*这里的警告是可以覆盖object_id,但它不会对比较产生影响,因为equal?实际上并没有使用object_id. 此外,重新定义equal?会改变这一点,但在 Ruby 文档中不明确建议这样做。

于 2013-01-13T16:42:29.103 回答