我在Ruby中有一个集合,它将保存我创建的类的对象。我正在使用该集来防止重复值,但我仍然在集合中获得重复值。假设它是因为集合中的对象,即使它们具有相同的值,它们也具有不同的地址。以下是我的内容:
sample_set = Set.new
sample_set的当前输出:
{
#<SampleModule: : SampleClass: 0x007fba92923ae8@name="Hello World!",
@id=123>,
#<SampleModule: : SampleClass: 0x007fba92922fd0@name="Hello World!",
@id=123>,
#<SampleModule: : SampleClass: 0x007fba92922418@name="Star Wars",
@id=456>,
#<SampleModule: : SampleClass: 0x007fba929217c0@name="Star Wars",
@id=456>,
#<SampleModule: : SampleClass: 0x007fba92920ac8@name="Star Wars",
@id=456>
}
sample_set的预期输出:
{
#<SampleModule: : SampleClass: 0x007fba92923ae8@name="Hello World!",
@id=123>,
#<SampleModule: : SampleClass: 0x007fba929217c0@name="Star Wars",
@id=456>
}
是否有可能在红宝石中实现这一目标?我们是否需要覆盖'eql'方法来执行此操作?
解决方案:
def eql?(other)
other.instance_of?(self.class) && @name == other.name && @id == other.id
end
def hash
@name.hash ^ @id.hash
end
答案 0 :(得分:3)
(从上面的评论中移出)
你可能没有覆盖#hash和#eql?在您的SampleClass中。为了使哈希和集合等数据结构正常工作,您需要这样做。
编程语言具有对象相等的概念,通常由某种等式函数和散列函数(Ruby中的eql?和hash)组成。该语言使用相等函数来确定两个对象是否相等。散列函数为某些数据结构(如集合和散列表)使用的每个对象计算散列(唯一值)。重要的是,如果两个对象相等(就eql而言?),必须具有相同的哈希值,否则哈希表和集将无法正常运行。
我的Ruby有点生疏,但对于SampleClass来说可能看起来像这样:
class SampleClass
...
def eql? other
other.instance_of?(self.class)
&& @id == other.id
&& @name == other.name
end
# delegate to hash function of whatever primitive @id and @name are
# probably Fixnum and String?
# Uses two prime numbers, adapted from Effective Java by Joshua Bloch
def hash
p, q = 17, 37
p = q * @id.hash
p = q * @name.hash
end
...
end