Redéfinition opérateur de vaisseau spatial de Ruby <=>
-
27-09-2019 - |
Question
Je suis en train de remplacer l'opérateur de Ruby <=> (vaisseau spatial) pour les pommes et les oranges tri afin que les pommes viennent d'abord triés en poids, et les oranges seconde, triées par douceur. Comme ceci:
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
Mais cela ne fonctionne pas, quelqu'un peut-il dire ce que je fais mal ici, ou une meilleure façon de le faire?
La solution
Votre problème est que vous n'initialise l'une des propriétés de chaque côté, l'autre sera toujours nil
. nil
n'a pas été traité dans le procédé de Array#<=>
, qui finit par tuer le tri.
Il y a quelques façons de traiter d'abord le problème serait quelque chose comme ceci
[self.weight.to_i, self.sweetness.to_i] <=> [other.weight.to_i, other.sweetness.to_i]
nil.to_i
vous donne 0
, qui laissera ce travail.
Autres conseils
Probablement fin, quand même ...
ajouter le suivant monkey-patch
class Array
def to_i(default=Float::INFINITY)
self.map do |element|
element.nil? ? default : element.to_i
end
end
end
Et changer le corps de Fruity::<=> to
[self.weight, self.sweetness].to_i <=> [other.weight, other.sweetness].to_i