在Ruby中创建对象哈希的最佳方法?

在Ruby中创建对象哈希的最佳方法?,ruby,Ruby,所以我有一个类,我需要重写相等运算符。这并不难。但是,除非两个比较对象的my_obj.hash相等,否则不会使用自定义相等运算符。所以我们需要重写hash() 我一直在想最好的办法。我的对象嵌入了另外三个对象实例。我通过示例看到,对于简单的实例变量,您可以对变量本身进行哈希: [var1, var2, var3].hash 更具体地说,我的类有三个嵌入对象的实例变量,我们称它们为: A 地下一层 B2 我的对象的两个实例相等,如果 object1.B1 == object2.B1 &&

所以我有一个类,我需要重写相等运算符。这并不难。但是,除非两个比较对象的my_obj.hash相等,否则不会使用自定义相等运算符。所以我们需要重写hash()

我一直在想最好的办法。我的对象嵌入了另外三个对象实例。我通过示例看到,对于简单的实例变量,您可以对变量本身进行哈希:

[var1, var2, var3].hash
更具体地说,我的类有三个嵌入对象的实例变量,我们称它们为:

A 地下一层 B2

我的对象的两个实例相等,如果

object1.B1 == object2.B1 && object1.B2 == object2.B2 || 
      object1.B1 == object2.B2 && object1.B2 == object2.B1
换句话说,B1和B2的集合中有相同的两个对象,而不管它们被分配到哪个特定的变量

B1和B2也有自定义的相等机制

我只是不清楚在这里重写hash()的最佳策略


很抱歉,如果示例是抽象的,我会尽量避免发布大量代码

我假设哈希值可以是任何对象,只要它在您的案例中的每个对象中都是唯一的。如果这个假设是正确的,例如,如何定义对象
hash()
方法作为数组返回

我不是100%清楚你想要实现什么。但是我已经解释了
self的顺序。B1
self。B2
并不重要。那么这是一种可能性:

def hash
  [self.B1.hash, self.B2.hash].sort
end
然后您可以将两个对象的
hash()

(my_obj1.hash == my_obj2.hash)

您的
B1
B2
对象可排序吗?如果是这样,下面是您的
hash
方法的一个简单实现:

class MyClass
  def hash
    return [self.B1, self.B2].sort.hash
  end
end
如果它们当前不可排序,并且按任何固有值对它们进行排序是没有意义的,则始终可以按
object\u id
进行排序:

class BClass
  include Comparable

  def <=> (other)
    case other
    when BClass then return (self.object_id <=> other.object_id)
    else return nil
    end
  end
end
但这意味着只有自我相同的对象才能正确地显示为相等,而不仅仅是“看起来”相似的对象。要理解我的意思,请比较以下内容:

# Comparison of look-alike objects
"a".object_id == "a".object_id  # => false

# Comparison of self-same objects
a = "a"
a.object_id == a.object_id      # => true

尝试使用集合而不是数组,这样顺序就不重要了。您必须在顶部有以下行:

require 'set'
然后创建一个包含这两个对象的集合,并使用它帮助实现相等运算符和哈希方法。我假设Set#hash行为正确,您可以在hash方法中使用它。Set#==可用于简化相等运算符


-1。这严重违反了
hash
的约定<指定code>hash返回一个
整数
@JörgWMittag什么是“合同”?默认情况下,
hash()
返回整数。因此,我同意任何常规库
hash()
必须返回整数。但是当一个人试图重新实现
hash()
时,我只是认为可以修改它,只要它在他们的框架内是一致的。如果他/她不喜欢它,那么他/她不会选择它。契约是
散列
a)将符合
的东西返回给int
契约,b)两个相等的对象具有相同的
散列
值。您的实现违反了a)点,例如,这将导致以下情况:
{StevesClass.new=>nil}#TypeError:没有将数组隐式转换为整数
<代码>[StevesClass.new,StevesClass.new].uniq#TypeError:数组未隐式转换为整数<代码>[StevesClass.new,StevesClass.new]。哈希#类型错误:数组未隐式转换为整数<代码>要求“设置”;设置[StevesClass.new,StevesClass.new]#类型错误:…@JörgWMittag我明白了
hash()
方法在内部用于各种目的,例如为哈希对象分配键。因此,重写它以返回除整数以外的任何内容都会在其他地方引起连锁反应。说得好。谢谢你的澄清。我现在想删除我的“答案”,但可能会把它留作这一点的参考……这很有启发性——我不会删除它。事实上,这正是我所做的。但感觉不对,我很高兴知道原因。谢谢。如果
B1
B2
不可排序,我支持这种方法。您的
hash
方法将与
返回集[self.B1,self.B2]一样简单。
require 'set'