compare two objects without take its ID in consideration

L

Lobosque Lucas

Is there a way to compare two objects without take its ID in
consideration? For example:

#<Game_Esper:0xdcc7e0 @str=6, @mdfel = 0, @name = "Ifrit"> ==
#<Game_Esper:0xeda51e @str=6, @mdfel = 0, @name = "Ifrit">

It'll return false, because the object ID is different. But i want it to
return true, because the arguments (is it the right name?) are all
equal.

Thanks
 
J

Jeremy Wells

Lobosque said:
Is there a way to compare two objects without take its ID in
consideration? For example:

#<Game_Esper:0xdcc7e0 @str=6, @mdfel = 0, @name = "Ifrit"> ==
#<Game_Esper:0xeda51e @str=6, @mdfel = 0, @name = "Ifrit">

It'll return false, because the object ID is different. But i want it to
return true, because the arguments (is it the right name?) are all
equal.

Thanks
You can overwrite the == method:

def ==(other_obj)
true if self.str == other_obj.str and self.mdfel == other_obj.mdfel
and self.name == other_obj.name
end
 
D

dblack

Hi --

confirm that
(1) the question was perfectly correct and normal (well I guess)
(2) Jeremy's answer too.
It just stroke me that maybe OP would have preferred not to post this
question and having followed a link in a hypothetical FAQ

Why not the real FAQ? http://www.rubygarden.org/faq


David

--
Q. What's a good holiday present for the serious Rails developer?
A. RUBY FOR RAILS by David A. Black (http://www.manning.com/black)
aka The Ruby book for Rails developers!
Q. Where can I get Ruby/Rails on-site training, consulting, coaching?
A. Ruby Power and Light, LLC (http://www.rubypal.com)
 
M

Mark Dodwell

It's not particularly nice but you could just do:

re = /:[^\s]*/
obj1.inspect.gsub(re, '') == obj2.inspect.gsub(re, '')
 
M

Mark Dodwell

This just gets the representation of both of the objects as strings (the
'inspect') part. Then it strips out the Object ID (the 'sub') part using
a regular expression. It's a bit ugly though.

It would be better to add an attribute to your object which acts as a
identifier for that object (in the real world), then you can simply
compare that to check two objects are the same. For example:

obj1.my_id == obj2.my_id

Hope that makes sense,

Mark
 
T

Tim Pease

You can overwrite the == method:

def ==(other_obj)
true if self.str == other_obj.str and self.mdfel == other_obj.mdfel
and self.name == other_obj.name
end

A little more robust ...

def ==( other )
return false unless Game_Esper === other

self.instance_variables.each do |v|
return false unless self.instance_variable_get(v) ==
other.instance_variable_get(v)
end
true
end


Blessings,
TwP
 
T

Tim Pease

A little, little more robust ...

def ==( other )
return false unless self.class === other

self.instance_variables.each do |v|
return false unless self.instance_variable_get(v) ==
other.instance_variable_get(v)
end
true
end


Blessings,
TwP
 
A

ara.t.howard

A little, little more robust ...

def ==( other )
return false unless self.class === other

self.instance_variables.each do |v|
return false unless self.instance_variable_get(v) ==
other.instance_variable_get(v)
end
true
end


careful:


harp:~ > cat a.rb
class C
def initialize
@this = self
end
def ==( other )
return false unless self.class === other
self.instance_variables.each do |v|
return false unless self.instance_variable_get(v) ==
other.instance_variable_get(v)
end
true
end
end

C.new == C.new


harp:~ > ruby a.rb
a.rb:8:in `==': stack level too deep (SystemStackError)
from a.rb:10:in `=='
from a.rb:8:in `=='
from a.rb:10:in `=='
from a.rb:8:in `=='
from a.rb:10:in `=='
from a.rb:8:in `=='
from a.rb:10:in `=='
from a.rb:8:in `=='
... 2489 levels...
from a.rb:8:in `=='
from a.rb:10:in `=='
from a.rb:8:in `=='
from a.rb:16


i prefer this pattern for the self documenting properties:

harp:~ > cat a.rb
class C
%w[ a b c ].each{|a| attr a}
def initialize a, b, c
@a, @b, @c = a, b, c
end
CMP_ATTRS = %w[ a b c ]
def == other
begin
x = CMP_ATTRS.map{|a| send a }
y = CMP_ATTRS.map{|a| other.send a }
x == y
rescue
false
end
end
end

p( C.new(1,2,3) == C.new(1,2,3) )
p( C.new(1,2,3) == C.new(2,3,4) )


harp:~ > ruby a.rb
true
false


though it too suffers from cyclical structures... sigh.

-a
 
I

Ilan Berci

Lobosque said:
Is there a way to compare two objects without take its ID in
consideration? For example:

#<Game_Esper:0xdcc7e0 @str=6, @mdfel = 0, @name = "Ifrit"> ==
#<Game_Esper:0xeda51e @str=6, @mdfel = 0, @name = "Ifrit">

It'll return false, because the object ID is different. But i want it to
return true, because the arguments (is it the right name?) are all
equal.

Thanks

class Game_Esper
def ==(other)
@str==other.str && @mdfel==other.mdfel && @name==other.name
end
end

If you have more state than this, I would suggest a looping construct
instead..

hope this helps

ilan
 
I

Ilan Berci

Ilan said:
class Game_Esper
def ==(other)
@str==other.str && @mdfel==other.mdfel && @name==other.name
end
end

If you have more state than this, I would suggest a looping construct
instead..

hope this helps

ilan


Actually, after submitting this, I realized that if 2 objects are equal
they should return the same hash, adjust accordingly :)
 
J

Joel VanderWerf

Lobosque said:
Is there a way to compare two objects without take its ID in
consideration? For example:

#<Game_Esper:0xdcc7e0 @str=6, @mdfel = 0, @name = "Ifrit"> ==
#<Game_Esper:0xeda51e @str=6, @mdfel = 0, @name = "Ifrit">

It'll return false, because the object ID is different. But i want it to
return true, because the arguments (is it the right name?) are all
equal.

This is one pattern I use, and (because it defines #eql? and #hash) it
also gives you the hashing behavior you will probably want to go with it:

module ContentEquality
def hash
content.hash
end

def eql?(other)
other.class == self.class and content.eql? other.content
end

def ==(other)
other.class == self.class and content == other.content
end
end

class Game
include ContentEquality
def initialize str, mdfel, name
@str, @mdfel, @name = str, mdfel, name
end

def content
[@str, @mdfel, @name]
end
end

g1 = Game.new "foo", "bar", "baz"
g2 = Game.new "foo", "bar", "baz"

p g1 == g2 # ==> true

h = {}
h[g1] = true
p h[g2] # ==> true
 
T

Tim Pease

i prefer this pattern for the self documenting properties:

harp:~ > cat a.rb
class C
%w[ a b c ].each{|a| attr a}
def initialize a, b, c
@a, @b, @c = a, b, c
end
CMP_ATTRS = %w[ a b c ]
def == other
begin
x = CMP_ATTRS.map{|a| send a }
y = CMP_ATTRS.map{|a| other.send a }
x == y
rescue
false
end
end
end

p( C.new(1,2,3) == C.new(1,2,3) )
p( C.new(1,2,3) == C.new(2,3,4) )


harp:~ > ruby a.rb
true
false


though it too suffers from cyclical structures... sigh.

Infinite recursion only bothers me when I have a finite processor ;)

Yeah, you can shoot yourself in the foot no matter how careful you
are. I did like Joel's "ContentEquality" pattern elsewhere in this
thread. I'm going to have to adopt that one.

Blessings,
TwP
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,901
Latest member
Noble71S45

Latest Threads

Top