我现在正在编写一个 Ruby 应用程序,它将在 Twitter 上搜索各种东西。我将面临的问题之一是在时间上彼此接近的搜索之间共享结果。结果以对象数组的形式返回,每个对象都是一条推文。我知道 Ruby 中的 Array.uniq 方法,它返回一个删除了所有重复项的数组。
我的问题是这个。只要这些对象指向内存中的相同空间或它们包含相同的信息,uniq 方法是否会删除重复项?
如果是前者,根据内容从数组中删除重复项的最佳方法是什么?
我现在正在编写一个 Ruby 应用程序,它将在 Twitter 上搜索各种东西。我将面临的问题之一是在时间上彼此接近的搜索之间共享结果。结果以对象数组的形式返回,每个对象都是一条推文。我知道 Ruby 中的 Array.uniq 方法,它返回一个删除了所有重复项的数组。
我的问题是这个。只要这些对象指向内存中的相同空间或它们包含相同的信息,uniq 方法是否会删除重复项?
如果是前者,根据内容从数组中删除重复项的最佳方法是什么?
只要这些对象指向内存中的相同空间或它们包含相同的信息,uniq 方法是否会删除重复项?
该方法依赖于该eql?
方法,因此它会删除 a.eql?(b) 返回 true 的所有元素。确切的行为取决于您正在处理的特定对象。
例如,如果字符串包含相同的文本,则认为它们是相等的,而不管它们共享相同的内存分配。
a = b = "foo"
c = "foo"
[a, b, c].uniq
# => ["foo"]
对于大部分核心对象都是如此,但对于 ruby 对象则不然。
class Foo
end
a = Foo.new
b = Foo.new
a.eql? b
# => false
Ruby 鼓励您==
根据类上下文重新定义运算符。
在您的特定情况下,我建议创建一个表示 twitter 结果的对象并实现您的比较逻辑,以便 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]
对于其他偶然发现这个问题的人来说,自从首次提出这个问题以来,事情似乎发生了一些变化,并且在较新的 Ruby 版本(至少 1.9.3)中,Array.uniq
假设您的对象还具有该#hash
方法的有意义的实现,此外到.eql?
或==
。
uniq
用途eql?
,如本线程中所述。
请参阅官方 ruby 文档了解==
、equal?
和eql?
.
我相信通过对象或方法Array.uniq
检测重复项,这意味着它的比较基于内容,而不是内存中的位置(假设对象提供了基于内容的有意义的实现)。eql?
==
eql?