删除Ruby中的相同对象?

时间:2009-10-30 15:26:02

标签: ruby arrays no-duplicates

我正在编写一个Ruby应用程序,它将在Twitter上搜索各种内容。我要面对的问题之一是在时间上彼此非常接近的搜索之间的共享结果。结果以对象数组的形式返回,每个对象都是一条推文。我知道ruby中的Array.uniq方法返回一个删除了所有重复项的数组。

我的问题是这个。只要这些对象指向内存中的相同空间或者它们包含相同的信息,uniq方法是否会删除重复项?

如果是前者,那么根据内容从阵列中删除重复项的最佳方法是什么?

4 个答案:

答案 0 :(得分:10)

  

uniq方法是否删除重复项   就这些对象而言   内存中的相同空间或它们   包含相同的信息?

该方法依赖于eql?方法,因此它删除了a.eql?(b)返回true的所有元素。 确切的行为取决于您正在处理的具体对象。

例如,如果字符串包含相同的文本,则它们被认为是相等的,无论它们是否共享相同的内存分配。

a = b = "foo"
c = "foo"

[a, b, c].uniq
# => ["foo"]

对于核心对象的大多数情况都是如此,但对于红宝石对象则不然。

class Foo
end

a = Foo.new
b = Foo.new

a.eql? b
# => false

Ruby鼓励您根据类的上下文重新定义==运算符。

在您的具体情况下,我建议创建一个表示推特结果的对象并实现您的比较逻辑,以便Array.uniq的行为符合您的预期。

class Result

  attr_accessor :text, :notes

  def initialize(text = nil, notes = nil)
    self.text = text
    self.notes = notes
  end

  def ==(other)
    other.class == self.class &&
    other.text  == self.text
  end
  alias :eql? :==

end

a = Result.new("first")
b = Result.new("first")
c = Result.new("third")

[a, b, c].uniq
# => [a, c]

答案 1 :(得分:6)

对于其他任何绊倒这个问题的人来说,看起来事情已经发生了一些变化,因为这个问题是第一次被问及在较新的Ruby版本中(至少1.9.3),Array.uniq假设您的对象也有除.eql?==之外,#hash方法的有意义实施。

答案 2 :(得分:2)

uniq使用eql?,如this thread中所述。

有关==equal?eql?之间的区别,请参阅the official ruby documentation

答案 3 :(得分:0)

我相信Array.uniq通过对象'eql?==方法检测重复,这意味着它基于内容进行比较,而不是内存中的位置(假设对象提供了有意义的实现基于内容的eql?