在Ruby中比较对象

10

请考虑以下内容:

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

有没有一种方法可以检查相同类型的类中所有公共属性是否相等?

4个回答

10
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

但是如果我想使用其他类来完成这个任务怎么办?或者如果有100个属性呢? - dfens
5
在你的方法中,你可以使用self.instance_variables.each do |ivar| self.ivar == other.ivar来比较实例变量。你可能还需要查看===。 - Jason Noble
1
使用 StructOpenStruct 已经内置了这些类型的情况。 - yurisich

9
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对象的ab的值相等,则它们相等。它还定义了initialize方法,让您在创建对象时可以选择传入ab的值(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

这看起来不错,但我需要这个功能用于对象,无论如何,很好的回应,我不知道结构体。 - dfens
1
@dfens:这些都是对象。Struct.new只是类的工厂方法。如果您使用class关键字定义Aaa,然后自己定义==等,您将获得完全相同的行为。 - sepp2k

2
我们可以很容易地推广到任意数量的实例,并且不需要为实例变量添加getter方法:
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

0

在 Ruby 中处理对象比较的另一种方法是使用 hash。出于性能原因,当类很大时,最好使用 hash 来比较 Ruby 对象,如下所示:

class Aaa
  attr_accessor :a, :b

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

  def hash(target)
     @a.hash == target.a.hash  && @b.hash == target.b.hash 
  end
end

A = new Aaa('whatever','whenever')
B = new Aaa('however','whoever')
A.hash(B)

这样做不会按预期工作。两个不同的不相等对象可以具有相同的哈希值,而同一对象在 Ruby 的调用之间可能没有相同的哈希值。此外,#hash 应该返回一个整数,而不是布尔值。这只有在快速检查两个值是否可能相等以及将键分组到哈希中以进行快速查找时才有用。 - Diego

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接