有没有一种智能的方法来检查自定义对象是否在数组中?

时间:2012-01-19 21:36:50

标签: ruby arrays object

鉴于我有自定义类arr的{​​{3}} My_class个实例。这个类有几个不同的实例变量。我们称它们为:name(一个字符串),:is_processed(一个布尔值)和:date(一个array)。所有这些都是可读的。

检查的最佳方法是什么,My_class(称之为newbe)的另一个给定实例是否已基于上述实例变量的内容在数组中?

使用arr.include?(newbe)将无效,因为这会比较对象ID,不是吗? 我可以覆盖Array#include?比较两个对象的方式吗?


在代码中说话

class My_class
  attr_reader :name, :is_processed, :date

  def initialize(_name, _proc, _d)
    @name = _name
    @is_processed = _proc
    @date = _d
  end
end

其他地方

first = My_class.new("First", false, DateTime.new(2001,2,3,4,5,6))
second = My_class.new("Second", true, DateTime.new(2001,2,3,4,5,6))
third = My_class.new("Third", false, DateTime.new(2001,2,3,3,2,1))
newbe = My_class.new("Second", true, DateTime.new(2001,2,3,4,5,6))

arr = [first, second, third]
arr.include?(newbe)  # => false but should be true

3 个答案:

答案 0 :(得分:3)

您希望比较某个类的实例,因此请添加comparable,定义<=>方法,并将这些方法添加到类实例中:

&lt;,&lt; =,==,&gt;,&gt; =,介于两者之间? (#include?使用#==)。

require 'date'
class My_class
  include Comparable
  attr_reader :name, :is_processed, :date

  def initialize(_name, _proc, _d)
    @name = _name
    @is_processed = _proc
    @date = _d
  end

  def <=>(other)
    [self.name, self.is_processed, self.date]<=>[other.name, other.is_processed, other.date]
  end
end
first = My_class.new("First", false, DateTime.new(2001,2,3,4,5,6))
second = My_class.new("Second", true, DateTime.new(2001,2,3,4,5,6))
third = My_class.new("Third", false, DateTime.new(2001,2,3,3,2,1))
newbe = My_class.new("Second", true, DateTime.new(2001,2,3,4,5,6))

arr = [first, second, third]
p arr.include?(newbe)  # => true
#you could do arr.sort, but they are sorted allready by accident...

答案 1 :(得分:2)

any?与块一起使用。

my_arr.any? { |o| o.kind_of?(MyClass) }

如果您想要匹配的对象,您还可以使用detectfind。这些都是Enumerable上的标准方法,大多数集合类都混合在一起。

答案 2 :(得分:2)

您应该考虑为自定义类重新定义==是否有意义,如下所示:

class My_class
  def ==(other)
    (other.is_a? My_class) && 
    (other.name == @name)  &&
    (other.is_processed == @is_processed) &&
    (other.date == @date)
  end
end

如果你这样做,Array #include?会以你想要的方式工作。