0Pricing
Ruby Academy · レッスン

Comparable と Enumerable

標準的なミックスインです。

「Comparable と Enumerable」はCoddyKit上の無料Ruby Academyレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはRuby Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Ruby Academyコースには全4レッスンが含まれています。

標準ミックスイン

Rubyには、自分のクラスにミックスインできる強力なモジュールが用意されています。代表的なものがComparableとEnumerableです。どちらも、1つのメソッドを実装するだけで多くのメソッドを利用できるようにします。

puts Comparable.instance_methods.sort.inspect

Comparableには<=>が必要

Comparableでは、-1、0、1のいずれかを返すスペースシップ演算子<=>を定義する必要があります。その代わりに、<、<=、==、>、>=、between?を利用できるようになります。

class Weight
  include Comparable
  attr_reader :grams
  def initialize(g); @grams = g; end
  def <=>(other); grams <=> other.grams; end
end
puts Weight.new(50) < Weight.new(80)

比較メソッドをすべて利用できる

1つの演算子を定義するだけで、すべての比較メソッドが動作するようになります。

class Weight
  include Comparable
  attr_reader :grams
  def initialize(g); @grams = g; end
  def <=>(other); grams <=> other.grams; end
end
a = Weight.new(100)
b = Weight.new(100)
puts a == b
puts Weight.new(30).between?(Weight.new(10), Weight.new(50))

Comparable の clamp

Comparableには、値を範囲内に収めるclampも用意されています。

puts 15.clamp(0, 10)
puts (-5).clamp(0, 10)
puts 7.clamp(0, 10)

Comparable オブジェクトのソート

<=>が定義されているため、独自のオブジェクトの配列は自動的にソートできます。

class Weight
  include Comparable
  attr_reader :grams
  def initialize(g); @grams = g; end
  def <=>(other); grams <=> other.grams; end
  def to_s; "#{grams}g"; end
end
list = [Weight.new(30), Weight.new(10), Weight.new(20)]
puts list.sort.map(&:to_s).inspect

Enumerable に必要な each

Enumerableでは、eachを定義する必要があります。定義すると、map、select、reduce、min、max、sortなど、数十種類以上のメソッドを利用できます。

class TodoList
  include Enumerable
  def initialize(*items); @items = items; end
  def each(&block); @items.each(&block); end
end
list = TodoList.new("buy milk", "call mom")
puts list.map(&:upcase).inspect

集計機能を無料で利用

eachを用意すると、count、min、include?などの集計用メソッドを利用できます。

class Scores
  include Enumerable
  def initialize(*n); @n = n; end
  def each(&block); @n.each(&block); end
end
s = Scores.new(8, 3, 9, 4)
puts s.max
puts s.min
puts s.count

select と reject

フィルタリング用のメソッドも利用できるようになります。

class Numbers
  include Enumerable
  def initialize(*n); @n = n; end
  def each(&block); @n.each(&block); end
end
nums = Numbers.new(1, 2, 3, 4, 5, 6)
p nums.select(&:even?)
p nums.reject(&:even?)

合計に使う reduce

reduce(別名はinject)は要素をまとめるメソッドで、たとえば要素の合計を計算できます。

class Basket
  include Enumerable
  def initialize(*p); @p = p; end
  def each(&block); @p.each(&block); end
end
b = Basket.new(10, 20, 30)
puts b.reduce(0) { |sum, price| sum + price }

2 つのミックスインを組み合わせる

ソートにはComparable、反復処理にはEnumerableを追加すると、クラスが組み込みのコレクションのように使えるようになります。

class Playlist
  include Enumerable
  def initialize(*songs); @songs = songs; end
  def each(&block); @songs.each(&block); end
end
pl = Playlist.new("c", "a", "b")
puts pl.sort.inspect
puts pl.first

まとめ

標準ミックスインは、わずかな契約を実装するだけで多くの機能を提供します。

  • Comparable:<=>を定義すると、すべての比較機能を利用できます。
  • Enumerable:eachを定義すると、コレクション操作の機能一式を利用できます。
class Bag
  include Enumerable
  def initialize(*x); @x = x; end
  def each(&b); @x.each(&b); end
end
puts Bag.new(3, 1, 2).sort.inspect

確認

標準ミックスインについての理解度を確認しましょう。

振り返り

標準ミックスインについて学びました。

  • Comparableには<=>が必要で、比較機能とclamp、between?が提供されます。
  • Enumerableにはeachが必要で、map、select、reduce、min、maxなどが提供されます。
  • 組み合わせると、独自のクラスを組み込み型のように使えるようになります。
class Temp
  include Comparable
  attr_reader :deg
  def initialize(d); @deg = d; end
  def <=>(o); deg <=> o.deg; end
end
puts Temp.new(20) > Temp.new(15)

よくある質問

「Comparable と Enumerable」レッスンは無料ですか?

はい。「Comparable と Enumerable」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Ruby Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Ruby Academyコースには全4レッスンが含まれています。

「Comparable と Enumerable」で何を学びますか?

標準的なミックスインです。 ブラウザで直接実行するハンズオンコードでRuby Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Ruby Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのRuby Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。

「Comparable と Enumerable」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このRuby Academyレッスンでコードを書いて実行できますか?

はい。すべてのRuby Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. モジュールの定義
  2. include と extend
  3. Comparable と Enumerable
  4. prepend とメソッド探索
← Ruby Academyに戻る