【问题标题】:Removing Identical Objects in Ruby?在 Ruby 中删除相同的对象?
【发布时间】:2009-10-30 15:26:02
【问题描述】:

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

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

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

【问题讨论】:

    标签: ruby arrays no-duplicates


    【解决方案1】:

    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]
    

    【讨论】:

    • 谢谢,我在课堂上实现了所需的方法,现在它似乎可以工作了。幸好我唯一真正需要比较的是每条推文的唯一 ID :) 我认为 other.class = self.class 应该是 other.class == self.class
    • 如果不覆盖hash 方法,我也无法让它工作。见rabbitcreative.com/2008/01/23/…
    【解决方案2】:

    对于遇到这个问题的其他人来说,自从第一次提出这个问题并且在较新的 Ruby 版本(至少 1.9.3)中,事情似乎发生了一些变化,Array.uniq 假设您的对象也有一个有意义的实现#hash 方法,除了.eql?==

    【讨论】:

      【解决方案3】:

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

      请参阅the official ruby documentation,了解==equal?eql? 之间的区别。

      【讨论】:

        【解决方案4】:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2020-06-27
          • 1970-01-01
          • 2017-06-26
          • 1970-01-01
          • 2014-06-05
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多