2010-10-15 3 views
5

Рассмотрим это:Сравнение объектов в рубин

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 

Есть ли какой-нибудь способ, чтобы проверить, если все государственные атрибуты равны в классах того же типа?

ответ

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

Но что, если я хочу сделать это, используя другие классы? Или, если есть 100 атрибутов? – dfens

+4

В вашем == (другом) методе вы можете сделать self.instance_variables.each do | ivar | self.ivar == other.ivar end Возможно, вы захотите посмотреть на ===. –

+0

работал для меня, спасибо – 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== определяет, eql? и hash для вас, так что два Aaa s равны, если их значения для a и b равны. Он также определяет initialize, так что вы можете при желании передать значения для a и b при создании объекта (Aaa.new(value_for_a, value_for_b)). И он определяет to_a для возврата [a,b].

Вы также можете использовать Struct.new с блоком для определения дополнительных методов, поэтому у вас есть все возможности «нормального» класса:

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

Это кажется прекрасным, но мне нужна эта функциональность для объектов, в любом случае приятный ответ, который я не знал о Structs – dfens

+1

@dfens: Это объекты. 'Struct.new' - всего лишь фабричный метод для классов. Вы бы получили то же самое поведение, если бы вы определили 'Aaa', используя ключевое слово' class', а затем определили '==' и т. Д. Самостоятельно. – sepp2k

0

Дополнительный метод для решения сравнения объектов в Ruby, состоит при использовании hash. По причине производительности, когда класс огромен, лучше всего использовать hash для сравнения рубина объектов, как так:

класса Aaa attr_accessor: а,: б

Защиты инициализировать (value_a, value_b) @a = value_a @b = value_b конец

Защита хэш (целевые) @ a.hash == target.a.hash & & @ b.hash == target.b.hash конца конца

A = новый Ааа ('независимо', 'когда') B = новый Ааа ('однако', 'кто') A.hash (B)

1

Мы можем легко обобщить на любое количество экземпляров и падение требования добытчиков для переменного экземпляра:

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 

Изменить z на:

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

затем:

x.instance_variables.map do |v| 
    arr.map { |i| i.send(:instance_variable_get,v) }.uniq.size == 1 
end.all? 
    #=> false 
Смежные вопросы