1

最初に以下のコードのパート I を実行し、目的の出力を取得しました。次に、それをいじって、パート II を行った調査を行うだけです。

パートI

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"

パート II

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"]パート I とパート II で異なる値を与えるのに、 では同じではないのはなぜh1[:c]ですか?

Ruby 1.9.3 を使用しています。

4

1 に答える 1

14

これを言うためのドキュメントcompare_by_identity

キーhshを ID で比較します。つまり、まったく同じオブジェクトを同じキーと見なします。

通常、ハッシュ キーは を使用して照合されますがeql?compare_by_identity代わりに を使用して照合されます(これはs* のequal?比較とほぼ同等です)。object_id同じ値を持つ文字列の異なるインスタンスには異なるobject_ids があるため、一致しません。ただし、シンボルは常に同じ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'

ご覧のとおり、文字列のs はハッシュ内のキーの s とobject_id一致しませんが、シンボルは一致します。object_id実際、'a'.object_id&を繰り返し実行'b'.object_id(または任意の文字列を呼び出しobject_id) すると、毎回異なる値が得られます。

*ここでの注意点は、 をオーバーライドできることですが、実際には を使用しないobject_idため、比較には影響しません。さらに、再定義するとこれが変更されますが、そうすることは Ruby ドキュメントで明示的に推奨されていません。equal?object_idequal?

于 2013-01-13T16:42:29.103 に答える