ruby - 如何为包含可比较的类定义哈希函数?

标签 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

在这种情况下,您将如何实现 hash 函数使得 a.hash == b.hash?一般来说,我会这样做:

def hash
  @name.hash
end

但这不包括pos_xpos_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'}

但是

{pos_x: 1, pos_y: 1, name: 'a'} != {pos_x: 2, pos_y: 2, name: 'b'}

这就是问题的根源。

关于ruby - 如何为包含可比较的类定义哈希函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22276046/

相关文章:

ruby-on-rails - Rails - request.env ['HTTP_X_FORWARDED_FOR' ] 和 request.remote_ip 之间的区别

c# - 散列 Json 结果以检测变化

ruby - 合并哈希数组

java - 具有可比性与 TreeSet 的列表

ruby - 哈希到数组转换

ruby - 直通方法

ruby-on-rails - 设计首次使用 Rails 登录

ruby - 如何在 Ruby 中为嵌套哈希使用动态变量名?

java - 根据值对 List<Map<String,Object>> 进行排序

java - 比较 VS <?扩展比较>