【问题标题】:How does Ruby's Array.| compare elements for equality?Ruby 的数组如何。比较元素是否相等?
【发布时间】:2010-03-27 15:45:09
【问题描述】:

下面是一些示例代码:

class Obj
  attr :c, true

  def == that
    p '=='
    that.c == self.c
  end
  def <=> that
    p '<=>'
    that.c <=> self.c
  end
  def equal? that
    p 'equal?'
    that.c.equal? self.c
  end
  def eql? that
    p 'eql?'
    that.c.eql? self.c
  end
end

a = Obj.new
b = Obj.new

a.c = 1
b.c = 1

p [a] | [b]

它打印 2 个对象,但它应该打印 1 个对象。没有一个比较方法被调用。数组怎么样。|比较是否相等?

【问题讨论】:

    标签: ruby


    【解决方案1】:

    Array#| 是使用散列实现的。因此,为了使您的类型能够很好地使用它(以及与哈希图和哈希集),您必须实现 eql?(您已执行)和 hash(您未执行)。有意义地定义散列的最直接的方法是只返回c.hash

    【讨论】:

    • 只是为了确认 -- Ruby 的 Array#hash 方法是否保证当且仅当数组的内容相等时值才会相等?
    • @EricWalker 否。如果(但不仅限于)两个数组包含具有相同哈希值且顺序相同的元素,则可以保证两个数组的哈希值相等。然而,这与这个问题无关,因为这里的 hash 只在元素上调用,而不是在数组本身上。
    【解决方案2】:

    Ruby 的 Array 类是用 C 实现的,据我所知,在比较 | 中的对象时,它使用自定义哈希表来检查是否相等。如果您想修改此行为,则必须编写自己的版本,使用您选择的相等检查。

    要查看 Ruby 的 Array#| 的完整实现:​​click here 并搜索“rb_ary_or(VALUE ary1, VALUE ary2)

    【讨论】:

      【解决方案3】:

      Ruby 正在调用散列函数并且它们返回不同的值,因为它们仍然只是返回默认的 object_id。您将需要 def hash 并返回一些反映您对什么使 Obj 重要的想法的内容。

      >> class Obj2 < Obj
      >>   def hash; t = super; p ['hash: ', t]; t; end
      >> end
      => nil
      >> x, y, x.c, y.c = Obj2.new, Obj2.new, 1, 1
      => [#<Obj2:0x100302568 @c=1>, #<Obj2:0x100302540 @c=1>, 1, 1]
      >> p [x] | [y]
      ["hash: ", 2149061300]
      ["hash: ", 2149061280]
      ["hash: ", 2149061300]
      ["hash: ", 2149061280]
      [#<Obj2:0x100302568 @c=1>, #<Obj2:0x100302540 @c=1>]
      

      【讨论】:

        猜你喜欢
        • 2012-02-15
        • 2012-10-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-02-12
        • 1970-01-01
        • 2011-11-20
        • 1970-01-01
        相关资源
        最近更新 更多