ruby中的Set如何比较元素



我正在尝试将自定义对象放入一个集合中。我试过这个:

require 'set'
class Person
include Comparable
def initialize(name, age)
@name = name
@age = age
end
attr_accessor :name, :age
def ==(other)
@name == other.name
end
alias eql? ==
end
a = Person.new("a", 18)
b = Person.new("a", 18)
people = Set[]
people << a
people << b
puts a == b # true

Set似乎不能用Object#eql?==方法识别相同的对象:

puts people # #<Set: {#<Person:0x00007f9e09843df8 @name="a", @age=18>, #<Person:0x00007f9e09843da8 @name="a", @age=18>}>

Set如何识别两个相同的对象?

来自文档:

Set使用Hash作为存储,因此必须注意以下几点:

  • 元素的相等性根据Object#eql?Object#hash来确定。[…]

也就是说:如果你想让两个人在同名时相等,那么你必须相应地实现hash

def hash
@name.hash
end
Ruby内置的Set将项目存储在Hash中。因此,要使对象被Set视为"相同",还需要定义一个自定义的hash方法。像这样的东西会起作用:
def hash
@name.hash
end

使用gem which set.rb查看Set的源代码存储在哪里,并尝试通读它。它清晰且编写良好。

最新更新