While writing an acceptance test, I needed to compare two sets of sets
of integers:
require 'set'
a = Set.new([Set.new([3,4]), Set.new([5,6])])
b = Set.new([Set.new([3,4]), Set.new([5,6])])
puts #{a == b}\n"
prints out 'false'.
Apparently the built-in Set library uses Hash#includes? to determine if
an object is in the rhs set. This method appears to use object id, so
set equality is based on set member object id.
A naive #==(set) that works the way I think it should is pretty simple:
def Set.my_eql?(set)
...
# this is the only part of my_eql? that differs from #==(set),
# replacing the line 'set.all? { |o| hash.include?(o) }'
set.all? { |o| @hash.each_value do |my_o|
if my_o == o
last true
end
false
end
}
end
I'm sure this has come up before... is there a better solution? This
one is fine for my purposes, but I would be nice there was a packaged
solution out there.
While writing an acceptance test, I needed to compare two sets of sets
of integers:
require 'set'
a = Set.new([Set.new([3,4]), Set.new([5,6])])
b = Set.new([Set.new([3,4]), Set.new([5,6])])
puts #{a == b}\n"
prints out 'false'.
Apparently the built-in Set library uses Hash#includes? to determine if
an object is in the rhs set. This method appears to use object id, so
set equality is based on set member object id.
A naive #==(set) that works the way I think it should is pretty simple:
def Set.my_eql?(set)
You'd want that to be an instance method, not a class method:
class Set
def my_eql?(set)
...
# this is the only part of my_eql? that differs from #==(set),
# replacing the line 'set.all? { |o| hash.include?(o) }'
set.all? { |o| @hash.each_value do |my_o|
if my_o == o
last true
end
false
end
}
end
You could just do:
set.all? {|x| any? {|y| x == y } }
I'm sure this has come up before... is there a better solution? This
one is fine for my purposes, but I would be nice there was a packaged
solution out there.
It did come up, quite recently I think. I can't remember what the
consensus was, if any.
> While writing an acceptance test, I needed to compare two sets of sets
> of integers:
>
> require 'set'
> a = Set.new([Set.new([3,4]), Set.new([5,6])])
> b = Set.new([Set.new([3,4]), Set.new([5,6])])
> puts #{a == b}\n"
>
> prints out 'false'.
>
> Apparently the built-in Set library uses Hash#includes? to determine if
> an object is in the rhs set. This method appears to use object id, so
> set equality is based on set member object id.
>
> A naive #==(set) that works the way I think it should is pretty simple:
>
> def Set.my_eql?(set)
You'd want that to be an instance method, not a class method:
class Set
def my_eql?(set)
Whoops
> ...
> # this is the only part of my_eql? that differs from #==(set),
> # replacing the line 'set.all? { |o| hash.include?(o) }'
>
> set.all? { |o|
> @hash.each_value do |my_o|
> if my_o == o
> last true
> end
> false
> end
> }
> end
You could just do:
set.all? {|x| any? {|y| x == y } }
Wow, that's almost mathematical set notation! Nice.
···
On Thu, 2005-09-22 at 02:16 +0900, David A. Black wrote:
On Thu, 22 Sep 2005, Gary Shea wrote:
> I'm sure this has come up before... is there a better solution? This
> one is fine for my purposes, but I would be nice there was a packaged
> solution out there.
It did come up, quite recently I think. I can't remember what the
consensus was, if any.
The above solution of set.all? {|x| any? { |y| x== y} } is not a full
solution. This will only work if you have set-nesting as described in
the original problem, but not if you have higher nesting (because then
you run back into the same original problem except one nesting level
down).
If this was the actual definition of ==, then it would work of course
:).