2010-06-17 58 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