読者です 読者をやめる 読者になる 読者になる

Bye Bye Moore

猫マンション建築の野望を胸に零細事業主として資本主義の荒波に漕ぎ出したアラサー男の技術メモ

Comparebleを使って自前クラスにsortの挙動を実装する(その2)

大分間が空きましたが、shuzo-kino.hateblo.jp
の続きです。<=>メソッドを定義すると、希望通りにソートしたり比較できたりするようになります。
#実際のところ
カードのレア度でソートする挙動を実現したいとします。
レア度は専用のクラスを定義し、それをCardクラスに読み込ませる形式をとります。
なお、カードは3つのグレードと、破損を意味するdamagedというパラメータを用意します。

class Rarity
  attr_reader :rarity

  def initialize(rarity = :common)
    @rarity = rarity
  end

  def <=>(other)
    rarity_tbl = {damaged: 0, common: 1, uncommon: 2, rare: 3}
    rarity_tbl[rarity] <=> rarity_tbl[other.rarity]
  end
end

class Card
  attr_reader :rarity, :name

  def initialize(rarity = :common, name)
    @rarity = Rarity.new(rarity)
    @name   = name
  end
end

ary = [] 
ary << Card.new(:rare,     :firefox) 
ary << Card.new(:common,    :ie)
ary << Card.new(:rare,     :chrome)
ary << Card.new(:uncommon, :opera)
ary << Card.new(:damaged,  :unknown)

pp ary.sort_by(&:rarity)

これを実行すると

$ ruby sort.rb 
[#<Card:0x007fcf2c857b88
  @name=:unknown,
  @rarity=#<Rarity:0x007fcf2c857b60 @rarity=:damaged>>,
 #<Card:0x007fcf2c857c78
  @name=:ie,
  @rarity=#<Rarity:0x007fcf2c857c50 @rarity=:common>>,
 #<Card:0x007fcf2c857bd8
  @name=:opera,
  @rarity=#<Rarity:0x007fcf2c857bb0 @rarity=:uncommon>>,
 #<Card:0x007fcf2c857c28
  @name=:chrome,
  @rarity=#<Rarity:0x007fcf2c857c00 @rarity=:rare>>,
 #<Card:0x007fcf2c857cc8
  @name=:firefox,
  @rarity=#<Rarity:0x007fcf2c857ca0 @rarity=:rare>>]

と、本来であればrarityのアルファベット順でソートされるところを意図した価値順でソートできます。