2010-10-15 18 views
5

Considera:comparar objetos en Ruby

class Aaa 
    attr_accessor :a, :b 
end 

x = Aaa.new 
x.a, x.b = 1,2 
y = Aaa.new 
y.a, y.b = 1,2 

puts x == y #=>false 

¿Hay alguna manera de comprobar si todos los atributos públicos son iguales en las clases de mismo tipo?

Respuesta

6
class Aaa 
    attr_accessor :a, :b 

    def ==(other) 
    return self.a == other.a && self.b == other.b 
    end 
end 

x = Aaa.new 
x.a,x.b = 1,2 
y = Aaa.new 
y.a,y.b = 1,2 
y = Aaa.new 
y.a,y.b = 1,2 
z = Aaa.new 
z.a,z.b = 1,3 

x == y # => true 
x == z # => false 
+0

¿Pero y si quiero hacer esto usando otras clases? O si hay 100 atributos? – dfens

+4

En su método == (other), podría hacer self.instance_variables.each do | ivar | auto.ivar == other.ivar end Es posible que también desee ver ===. –

+0

funcionó para mí, gracias – dfens

8
Aaa = Struct.new(:a, :b) 

x = Aaa.new 
x.a, x.b = 1,2 
y = Aaa.new 
y.a, y.b = 1,2 

x == y #=> true 

Struct define ==, eql? y hash para usted, por lo que dos Aaa s son iguales, si sus valores para a y b son iguales. También define initialize para que, opcionalmente, pueda ingresar los valores de a y b al crear el objeto (Aaa.new(value_for_a, value_for_b)). Y define to_a para devolver [a,b].

También puede utilizar Struct.new con un bloque para definir métodos adicionales, por lo que tiene todo el poder de una clase "normal":

Aaa = Struct.new(:a, :b) do 
    def c 
    a+b 
    end 
end 
Aaa.new(23,42).C#=> 65 
+0

Esto parece bien, pero necesito esta funcionalidad de los objetos, de todos modos buena respuesta que no sabía nada de Structs – dfens

+1

@dfens: Esos son los objetos. 'Struct.new' es solo un método de fábrica para las clases. Obtendrá exactamente el mismo comportamiento si define 'Aaa' utilizando la palabra clave' class' y luego define '==' etc. usted mismo. – sepp2k

0

método adicional para hacer frente a la comparación de objetos en Ruby consiste al usar hash. Por motivos de rendimiento, cuando la clase son enormes, lo mejor es utilizar hash para comparar objetos rubí como tan:

clase Aaa attr_accessor: una,: b

def intialize (value_a, value_b) @ un = value_a @b = value_b extremo

def almohadilla (objetivo) @ a.hash == target.a.hash & & @ b.hash == target.b.hash extremo extremo

A = nueva Aaa ('lo que sea', 'siempre') B = new Aaa ('sin embargo', 'el que') A.hash (B)

1

podemos generalizar fácilmente a cualquier número de instancias y soltar el requisito de captadores para las variables de instancia:

class Aaa 
    def initialize(a,b,c) 
    @a, @b, @c = a, b, c 
    end 
end 

x = Aaa.new(1,2,3) 
y = Aaa.new(1,2,3) 
z = Aaa.new(1,2,3) 
arr = [x,y,z] 

x.instance_variables.map do |v| 
    arr.map { |i| i.send(:instance_variable_get,v) }.uniq.size == 1 
end.all? 
    #=>true 

Cambio z a:

z = Aaa.new(1,2,4) 

a continuación:

x.instance_variables.map do |v| 
    arr.map { |i| i.send(:instance_variable_get,v) }.uniq.size == 1 
end.all? 
    #=> false 
Cuestiones relacionadas