2010-06-17 77 views
4

我想重载Ruby的< =>(飞船)运营商排序苹果和橙子,这样苹果先按重量排序,再按橙色排序,按甜味排序。像这样:凌驾Ruby的飞船运营商<=>

module Fruity 
    attr_accessor :weight, :sweetness 

    def <=>(other) 
    # use Array#<=> to compare the attributes 
    [self.weight, self.sweetness] <=> [other.weight, other.sweetness] 
    end 
    include Comparable 
end 

class Apple 
include Fruity 

def initialize(w) 
    self.weight = w 
end 

end 

class Orange 
include Fruity 

def initialize(s) 
    self.sweetness = s 
end 

end 

fruits = [Apple.new(2),Orange.new(4),Apple.new(6),Orange.new(9),Apple.new(1),Orange.new(22)] 

p fruits 

#should work? 
p fruits.sort 

但是这不起作用,有人可以告诉我在这里做错了什么,或者更好的方法来做到这一点?

+3

作业的身体吗? :)... – devios1 2010-06-17 04:15:08

+0

更新:事实证明,我是这样做的错误方式。提示:答案在于 - http://blog.hasmanythrough.com/2008/8/17/sorting-things-out – 2011-12-10 00:22:04

回答

11

你的问题是你只是初始化任何一方的属性之一,另一个将仍然是nil。在Array#<=>方法中不处理nil,最终导致排序失败。

有几种方法可以先受理的问题将是这样的

[self.weight.to_i, self.sweetness.to_i] <=> [other.weight.to_i, other.sweetness.to_i] 

nil.to_i给你0,这将让这项工作。

+0

谢谢,它的工作。他们按重量顺序排列,然后按降序排列。有没有一种'最好的'方法来命令他们上升? – 2010-06-17 18:18:47

+0

让我澄清我上述comment--如果我做了以下变化: [self.weight.to_i,self.sweetness.to_i] <=> [other.weight.to_i,other.sweetness.to_i] 我得到橘子第一次上升,然后苹果上升,但我不能先苹果上升,然后橙子上升。我尝试过对数组进行排序,甚至用数组#反转而没有运气。 另外,如果在<=>定义之前或之后包含可比较的mixin,它无关紧要吗?无论哪种方式我都会得到类似的结果 – 2010-06-17 18:50:02

+0

它包含的内容并不重要。也许尝试result.sort.reverse?不是最好的方式,但可能是最直接的 – 2010-06-17 22:02:06

-1

大概晚了,不过......

添加以下猴补丁

class Array 
    def to_i(default=Float::INFINITY) 
    self.map do |element| 
     element.nil? ? default : element.to_i 
    end 
    end 
end 

,并更改Fruity::<=> to

[self.weight, self.sweetness].to_i <=> [other.weight, other.sweetness].to_i 
+0

对不起,但这是不好的建议。 (猴子补丁总是,但这个问题可以更好地解决)。像这样的猴子补丁可能会炸毁很多其他的东西。 – 2015-09-18 12:46:33