Bye Bye Moore

PoCソルジャーな零細事業主が作業メモを残すブログ

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のアルファベット順でソートされるところを意図した価値順でソートできます。