2010-10-15 12 views
5
Comparer

Considérez ceci:objets en rubis

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 

est-il un moyen de vérifier si tous les attributs publics sont égaux dans les classes de même type?

Répondre

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

Mais que faire si je veux le faire en utilisant d'autres classes? Ou s'il y a 100 attributs? – dfens

+4

Dans votre méthode == (autre), vous pouvez faire self.instance_variables.each faire | ivar | self.ivar == other.ivar end Vous pouvez aussi regarder ===. –

+0

travaillé pour moi, merci – 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 définit ==, eql? et hash pour vous, afin que deux Aaa s sont égaux, si leurs valeurs pour a et b sont égaux. Il définit également initialize afin que vous puissiez éventuellement transmettre les valeurs pour a et b lors de la création de l'objet (Aaa.new(value_for_a, value_for_b)). Et il définit to_a pour retourner [a,b].

Vous pouvez également utiliser Struct.new avec un bloc pour définir des méthodes supplémentaires, de sorte que vous avez la pleine puissance d'une classe « normale »:

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

Cela semble bien, mais j'ai besoin de cette fonctionnalité pour les objets, de toute façon belle réponse que je ne savais pas sur Structs – dfens

+1

@dfens: Ce sont des objets. 'Struct.new' est juste une méthode d'usine pour les classes. Vous obtiendriez exactement le même comportement si vous définissiez 'Aaa' en utilisant le mot-clé' class' et que vous définissiez '==' etc. – sepp2k

0

méthode supplémentaire pour faire face à la comparaison d'objets en Ruby se compose en utilisant hash. Pour des raisons de performance, lorsque la classe sont énormes, le mieux est d'utiliser hash pour comparer ruby ​​objets comme si:

classe Aaa attr_accessor: a,: b

def intialize (value_a, value_b) @a = value_a @b = value_b fin

hachage def (cible) @ a.hash == target.a.hash & & @ b.hash == target.b.hash extrémité extrémité

A = new Aaa ('tout', 'chaque fois') B = new Aaa ('mais', 'quiconque') A.hash (B)

1

On peut facilement généraliser à un nombre quelconque d'instances et laisser tomber l'exigence de getters pour les variables d'instance:

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 

Changement z à:

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

alors:

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