2010-10-15 15 views
5

Rozważ to:Porównywanie obiektów w 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 

Czy istnieje jakiś sposób, aby sprawdzić, czy wszystkie atrybuty publiczne są równe w klasach tego samego typu?

Odpowiedz

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

Ale co, jeśli chcę to zrobić na innych zajęciach? A może 100 atrybutów? – dfens

+4

W swojej == (innej) metodzie, można zrobić self.instance_variables.each do | ivar | self.ivar == other.ivar koniec Możesz również spojrzeć na ===. –

+0

pracował dla mnie, dziękuję – 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 definiuje ==, eql? i hash dla ciebie, tak, że dwa Aaa y są równe, jeśli ich wartości a i b są równe. Definiuje również initialize, dzięki czemu można opcjonalnie przekazać wartości a i b podczas tworzenia obiektu (Aaa.new(value_for_a, value_for_b)). I definiuje to_a, aby zwrócić [a,b].

Można również użyć Struct.new z bloku do określenia dodatkowych metod, więc masz pełną moc „normalnej” klasy:

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

Wydaje się, że to dobrze, ale potrzebuję tej funkcjonalności dla obiektów, w każdym razie niezła odpowiedź, której nie wiedziałem o strukturach – dfens

+1

@dfens: To są obiekty. 'Struct.new' jest po prostu metodą fabryczną dla klas. Otrzymasz dokładnie to samo zachowanie, jeśli zdefiniujesz 'Aaa' używając słowa kluczowego' class', a następnie sam zdefiniujesz '==' itd. – sepp2k

0

Extra metodę postępowania w porównywaniu obiektów w Ruby składa w użyciu hash. Ze względów wydajności, gdy klasa są ogromne, najlepiej jest użyć hash porównać rubin obiektów jak tak:

klasa Aaa attr_accessor: a,: b

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

def mieszania (docelowy) @ a.hash == target.a.hash & & @ b.hash == target.b.hash końcowego koniec

A = nowy AAA ('niezależnie', 'gdy') B = nowy AAA ('Jednakże', 'kto') A.hash (B)

1

Możemy łatwo uogólnienia do dowolnej liczby przypadków i spadek zapotrzebowania na pobierające dla zmiennych przykład:

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 

Zmiana z do:

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

wówczas:

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