I am trying to put custom objects in a set. I tried this:
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
It seems that Set does not identify same objects with Object#eql? or == methods:
puts people # #<Set: {#<Person:0x00007f9e09843df8 @name="a", @age=18>, #<Person:0x00007f9e09843da8 @name="a", @age=18>}>
How does Set identify two same objects?
From the docs:
SetusesHashas storage, so you must note the following points:
- Equality of elements is determined according to
Object#eql?andObject#hash. [...]
That said: If you want two people to be equal when they have the same name, then you must implement hash accordingly:
def hash
@name.hash
end
Ruby's built-in Set stores items in a Hash. So for your objects to be treated as the "same" by Set, you also need to define a custom hash method. Something like this would work:
def hash
@name.hash
end
Use gem which set.rb to see where the source code for Set is stored, and try reading through it. It's clear and well-written.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With