6

是否有一种简单的方法(即使用 spaceship 运算符)在 Ruby 中基于两个不同的属性定义比较?即,如果我有一个包含两个属性 attr1 和 attr2 的类,是否有一种 Rubyesque 方法可以在 attr1 上比较此类的两个实例,如果它们相等,则在 attr2 上比较它们?

4

3 回答 3

15

这是一种易于扩展(更多属性)的方式:

def <=>(other)
  [self.attr1, self.attr2] <=> [other.attr1, other.attr2]
end
于 2013-01-15T20:26:48.220 回答
7

可比较 mixin 的全部意义在于为 spaceship(比较)运算符提供定义。因此,如果您想对两个属性进行比较,那就去做吧。这是一个过于冗长的示例:

def <=>(obj)
  comparison = self.attr1 <=> obj.attr1

  if comparison == 0
    return self.attr2 <=> obj.attr2
  else
    return comparison
  end
end

显然,以上假设attr1,并且attr2两者都具有宇宙飞船运算符的定义。您还需要确定什么构成大于和小于,这在两个属性中可能有点困难。这表明可比较的代码可能不适合您的场景。


一种更简洁和惯用的写法是:

def <=>(obj)
  self.attr1 <=> obj.attr1 == 0 ? self.attr2 <=> obj.attr2 : self.attr1 <=> obj.attr1
end
于 2011-11-14T15:24:33.880 回答
2

具有“不可比性”的宇宙飞船

宇宙飞船需要:

a <=> b :=
  if a < b then return -1
  if a = b then return  0
  if a > b then return  1
  if a and b are not comparable then return nil  <= I wanted this

当“不可比较”时,Steenslag 的解决方案并没有给我零。

实施

为处理“不可比较”添加了额外的行:

def <=> other
  return nil unless other.is_a?(self.class)
  [self.attr1, self.attr2] <=> [other.attr1, other.attr2]
end
于 2014-08-14T17:28:21.600 回答