Forum: Ruby Array#-

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
3cab6e3dfe2dafb46913e660ec37c7c8?d=identicon&s=25 jogloran (Guest)
on 2006-04-13 16:23
(Received via mailing list)
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
E0ed615bd6632dd23165e045e3c1df09?d=identicon&s=25 Florian GroÃ? (Guest)
on 2006-04-13 16:39
(Received via mailing list)
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? :==
Dd76a12d66f843de5c5f8782668e7127?d=identicon&s=25 Mauricio Fernandez (Guest)
on 2006-04-13 16:42
(Received via mailing list)
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>]
3cab6e3dfe2dafb46913e660ec37c7c8?d=identicon&s=25 jogloran (Guest)
on 2006-04-14 04:37
(Received via mailing list)
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
E0d864d9677f3c1482a20152b7cac0e2?d=identicon&s=25 Robert Klemme (Guest)
on 2006-04-14 11:48
(Received via mailing list)
Why don't you just use a Set for storage of the values if that's what it
is?

Kind regards

robert
This topic is locked and can not be replied to.