Ruby 入門

Ruby case ステートメント

Ruby における case ステートメントは、マルチプルな条件ブランチ(分岐)をハンドリングするための、クリーンでリーダブル(可読性の高い)なアプローチを提供します。特に、単一のエクスプレッション(式)を複数の可能な値と対比させる必要がある場合、深くネストされた ifelsif、および else ステートメントよりもストラクチャー(構造)の面で大きなアドバンテージを持ちます。

本章では、case ステートメントのシンタックス(構文)、コアとなる機能、および高効率にユースするためのベストプラクティスについて探求します。これまでの条件ロジックの基礎に基づき、よりコンサイス(簡潔)でメンテナンスしやすいコードを記述する方法を学習していきましょう。

1. case ステートメントを理解する

case ステートメントは、エクスプレッションの値に基づいて異なるコードブロックをエグゼキュート(実行)することを許可します。これはエクスプレッションの値を一連の when 句とシーケンシャル(順番)に対比させ、マッチする項目が見つかると、即座に対応するコードブロックをエグゼキュートします。

1.1 ベーシックなシンタックス

case ステートメントのベーシックなシンタックス・フォーマットは以下の通りです:

case expression
when value1
  # expression == value1 の場合、ここのコードをエグゼキュートする
when value2
  # expression == value2 の場合、ここのコードをエグゼキュートする
else
  # 先行するすべての when 句がマッチしなかった場合、ここのコードをエグゼキュートする
end
  • expression (エクスプレッション):エバリュエート(評価)および対比を行いたい値です。
  • when value1:when 句は、エクスプレッションの値を value1 と対比させます。when 句は任意の数だけ記述することが可能です。
  • else:else 句はオプショナル(任意)です。これは、どの when コンディションにもマッチしなかった場合にエグゼキュートされるデフォルトのコードを指定します。else 句が記述されておらず、かつマッチする when 句も存在しない場合、case ステートメントは何もオペレーションを実行しません。
  • end:case ステートメント全体の終了をマークします。

1.2 シンプルなサンプル

シンプルな例を見てみましょう。指定されたストリング(文字列)に基づいてフルーツの種類をジャッジします:

fruit = "apple"

case fruit
when "apple"
  puts "これはリンゴです。"
when "banana"
  puts "これはバナナです。"
when "orange"
  puts "これはオレンジです。"
else
  puts "これはその他の種類のフルーツです。"
end

このサンプルにおいて、case ステートメントはバリアブル(変数) fruit の値をエバリュエートします。fruit"apple" であるため、最初の when 句がマッチし、プログラムは "これはリンゴです。" をアウトプットします。

2. when 句でのマルチプルな値のマッチング

1つの when 句にはマルチプルな(複数の)値を含めることができます。これは、異なるマッチング項目に対して同一のコードブロックをエグゼキュートできることを意味します。これらの値をカンマでセパレート(区切り)するだけで実装可能です。

2.1 マルチプル・マッチングのシンタックス

case expression
when value1, value2, value3
  # expression が value1、value2、または value3 に等しい場合、このコードをエグゼキュートする
else
  # どの when にもマッチしない場合、このコードをエグゼキュートする
end

2.2 マルチプル・マッチングのサンプル

ある曜日を「ワークデー(平日)」または「ウィークエンド(週末)」にカテゴライズする必要があると仮定します:

day = "Saturday"

case day
when "Monday", "Tuesday", "Wednesday", "Thursday", "Friday"
  puts "今日はワークデーです。"
when "Saturday", "Sunday"
  puts "今日はウィークエンドです。"
else
  puts "無効な日付です。"
end

上記のコードにおいて、最初の whenday がワークデーのいずれかであるかをチェックし、2番目の when はウィークエンドであるかをチェックします。day の値は "Saturday" であるため、2番目の when 句がマッチし、"今日はウィークエンドです。" がアウトプットされます。

3. when 句でのレンジ (Ranges) のユース

when 句は、Ruby のレンジ(Ranges)メカニズムの使用をパーフェクトにサポートしており、エクスプレッションの値が特定の区間内にフォール(該当)するかどうかをチェックするためにユースされます。これは、数値の大小のジャッジやアルファベット順の処理を行う際に非常に実用的です。

3.1 レンジ・マッチングのシンタックス

case expression
when range1
  # expression が range1 の範囲内にフォールする場合、このコードをエグゼキュートする
when range2
  # expression が range2 の範囲内にフォールする場合、このコードをエグゼキュートする
else
  # マッチ項目がない場合、このコードをエグゼキュートする
end

3.2 レンジ・マッチングのサンプル

例えば、学生のテストのスコアに基づいてレターグレード(文字成績)を評価したいとします:

score = 85

case score
when 90..100
  puts "A"
when 80..89
  puts "B"
when 70..79
  puts "C"
when 60..69
  puts "D"
else
  puts "F"
end

case ステートメントは、score がどのレンジにフォールするかをチェックします。8580..89 の間に属しているため、プログラムは "B" をアウトプットします。

4. when 句でのレギュラー・エクスプレッション (正規表現) のユース

when 句の中でレギュラー・エクスプレッション(Regular Expressions:正規表現)を使用し、ストリング内のパターンをマッチさせることが可能です。これは複雑なストリングのバリデーション(検証)をハンドリングするための強力なツールです。

4.1 正規表現マッチングのシンタックス

case expression
when /pattern1/
  # expression が pattern1 にマッチする場合、このコードをエグゼキュートする
when /pattern2/
  # expression が pattern2 にマッチする場合、このコードをエグゼキュートする
else
  # マッチ項目がない場合、このコードをエグゼキュートする
end

4.2 正規表現マッチングのサンプル

ログ(Log)のコンテンツに基づいてログ・インフォメーションをカテゴライズする必要があると仮定します:

log_message = "ERROR: File not found."

case log_message
when /ERROR/
  puts "これはエラー (Error) インフォメーションです。"
when /WARNING/
  puts "これはワーニング (Warning) インフォメーションです。"
when /INFO/
  puts "これはインフォ (Info) インフォメーションです。"
else
  puts "これはその他のタイプのログです。"
end

log_message"ERROR" というワードを含んでいるため、最初のレギュラー・エクスプレッション /ERROR/ がマッチし、"これはエラー (Error) インフォメーションです。" がアウトプットされます。

5. case ステートメントのリターン値

Ruby において、case ステートメント自体がリターン値(戻り値)を持っています。そのランタイム・リザルトを直接バリアブルにアサインすることが可能です。これは、マッチが成功した when または else 句の中で、最後にエバリュエートされたエクスプレッションの値をリターンします。

5.1 リターン値のサンプル

前述の成績評価コードをリファクタリングし、puts でプリントする代わりに、case ステートメントが直接グレードのストリングをリターンするようにしてみましょう:

score = 75

grade = case score
        when 90..100
          "A"
        when 80..89
          "B"
        when 70..79
          "C"
        when 60..69
          "D"
        else
          "F"
        end

puts "最終的な成績は: #{grade} です"

このシナリオでは、case ステートメントが score をエバリュエートし、マッチしたストリング "C" をリザルトとしてリターンし、それをバリアブル grade にアサインします。最終的なアウトプットは "最終的な成績は: C です" となります。

6. case ステートメント vs. if/elsif/else

caseif/elsif/else はどちらもマルチプルな条件ブランチをハンドリングできますが、それぞれに最適なアプリケーション・シナリオが存在します。

case ステートメントのユースを推奨するシナリオ:

  • 同一のエクスプレッションを、マルチプルなポテンシャル値(潜在的な値)と対比させる必要がある場合。
  • コードのリーダビリティとメンテナンス性を最優先事項とする場合。
  • ロジックが主に等価性(Equality)のチェックに基づいている場合(または when で容易に表現できるレンジやレギュラー・エクスプレッションである場合)。

if/elsif/else のユースを推奨するシナリオ:

  • 条件ロジックが非常に複雑であり、マルチプルな異なるバリアブルやエクスプレッションが関与している場合。
  • 完全に無関係なブーリアン・コンディション(Boolean conditions)に基づいて異なるオペレーションをエグゼキュートする必要がある場合。

総じて、caseif/elsif/else のどちらを選択するかは、多くの場合、個人的なプレファレンス(好み)やコードスタイルの問題となります。しかし、適切なシナリオで case ステートメントをユースすることで、コードをよりクリーンで直感的なものに保つことができる傾向にあります。