Array#-

I need items to be compared based on their values, and not by object
equality, so I provide #== for the array elements. The problem is that
I’ve
been trying to use Array#- as a set difference-like operation, and it
doesn’t seem to respect any kind of user-provided means of defining
equality. A look into the Ruby source seems to indicate that it works by
populating a hash with the elements of the second array, then appending
to
the result array if an element of the first array is in the hash. Does
this
mean that it is impossible to get the behaviour I want from Array#- as
it is
implemented?

Regards,

jogloran

jogloran wrote:

I need items to be compared based on their values, and not by object
equality, so I provide #== for the array elements. The problem is that I’ve
been trying to use Array#- as a set difference-like operation, and it
doesn’t seem to respect any kind of user-provided means of defining
equality. A look into the Ruby source seems to indicate that it works by
populating a hash with the elements of the second array, then appending to
the result array if an element of the first array is in the hash. Does this
mean that it is impossible to get the behaviour I want from Array#- as it is
implemented?

Nope, you just need to redefine hash and alias == as eql?.

This will work:

def hash()

But it’s a good idea to actually define this in a meaningful way so

that putting the object into hashes is efficient.

0
end

alias :eql? :==

On Thu, Apr 13, 2006 at 11:21:18PM +0900, jogloran wrote:

I need items to be compared based on their values, and not by object
equality, so I provide #== for the array elements. The problem is that I’ve
been trying to use Array#- as a set difference-like operation, and it
doesn’t seem to respect any kind of user-provided means of defining
equality. A look into the Ruby source seems to indicate that it works by
populating a hash with the elements of the second array, then appending to
the result array if an element of the first array is in the hash. Does this
mean that it is impossible to get the behaviour I want from Array#- as it is
implemented?

You have to define #hash and #eql?:

RUBY_VERSION # => “1.8.4”
class X
attr_reader :foo
def initialize(foo); @foo = foo end
end

[X.new(1), X.new(2)] - [X.new(1)] # => [#<X:0xb7deaf94
@foo=1>, #<X:0xb7deaf80 @foo=2>]

X.new(1).hash # => -605071554
X.new(1).hash # => -605071594
class X
def hash
@foo.hash
end
def eql?(x)
foo == x.foo
end
end

[X.new(1), X.new(2)] - [X.new(1)] # => [#<X:0xb7dead50
@foo=2>]

Why don’t you just use a Set for storage of the values if that’s what it
is?

Kind regards

robert

Ah, thank you. But could this change in future versions? The fact that
the
operation is backed by a hash operation is not mentioned in the
documentation.

Thanks