Pad*_*i91 5 ruby hash comparable
想象一下包括类似这样的类:
class Element
include Comparable
attr_accessor :name, :pos_x, :pos_y
def initialize(name, pos_x, pos_y)
@name = name
@pos_x = pos_x
@pos_y = pos_y
end
def <=>(other)
if (@pos_x == other.pos_x) and (@pos_y == other.pos_y)
return 0
else
return @name <=> other.name
end
end
def eql?(other)
self == other
end
end
Run Code Online (Sandbox Code Playgroud)
在这种情况下hash,你将如何实现这个功能a.hash == b.hash?一般来说,我会这样做:
def hash
@name.hash
end
Run Code Online (Sandbox Code Playgroud)
但这不包括pos_x和pos_y.
不幸的是,在这种情况下,在数学上不可能定义有效的哈希函数。
设a、b是位置相同、名称不同的两个元素。根据eql?定义,这意味着h(a) == h(b). 由于这对于任何名称值都是如此,因此散列函数将独立于名称属性,但这与第二个检查相矛盾。因此,这个定义没有哈希函数eql?。对不起。:(
更新:
正如 toro2k 所指出的 - 你的平等定义是不可传递的。一般来说,如果a == b且b == c,则要求a == c。根据你的eql?功能:
{pos_x: 1, pos_y: 1, name: 'a'} == {pos_x: 1, pos_y: 1, name: 'b'}
{pos_x: 1, pos_y: 1, name: 'b'} == {pos_x: 2, pos_y: 2, name: 'b'}
Run Code Online (Sandbox Code Playgroud)
但
{pos_x: 1, pos_y: 1, name: 'a'} != {pos_x: 2, pos_y: 2, name: 'b'}
Run Code Online (Sandbox Code Playgroud)
这就是你问题的根源。