# Array#-

**URL:** <https://www.ruby-forum.com/t/array/93903>\
**Category:** Ruby\
**Created:** [April 13, 2006, 4:23pm UTC](https://www.ruby-forum.com/t/array/93903 "2006-04-13T16:23:57Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![jogloran](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/ac91a4/32.png) [@jogloran](https://www.ruby-forum.com/u/jogloran)\
**Post date:** [April 13, 2006, 4:23pm UTC](https://www.ruby-forum.com/t/array/93903/1 "2006-04-13T16:23:57Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![jogloran](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/ac91a4/32.png) [@jogloran](https://www.ruby-forum.com/u/jogloran)\
**Post date:** [April 13, 2006, 4:39pm UTC](https://www.ruby-forum.com/t/array/93903/2 "2006-04-13T16:39:14Z")

</div>

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? :==

---

<div class="post-metadata">

**Author:** ![jogloran](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/ac91a4/32.png) [@jogloran](https://www.ruby-forum.com/u/jogloran)\
**Post date:** [April 13, 2006, 4:42pm UTC](https://www.ruby-forum.com/t/array/93903/3 "2006-04-13T16:42:25Z")

</div>

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\>]

---

<div class="post-metadata">

**Author:** ![jogloran](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/ac91a4/32.png) [@jogloran](https://www.ruby-forum.com/u/jogloran)\
**Post date:** [April 14, 2006, 11:48am UTC](https://www.ruby-forum.com/t/array/93903/4 "2006-04-14T11:48:11Z")

</div>

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

Kind regards

robert

---

<div class="post-metadata">

**Author:** ![jogloran](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/ac91a4/32.png) [@jogloran](https://www.ruby-forum.com/u/jogloran)\
**Post date:** [April 14, 2006, 4:37am UTC](https://www.ruby-forum.com/t/array/93903/5 "2006-04-14T04:37:40Z")

</div>

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
