更新日:
【Ruby】 case whenによる条件分岐を基礎から応用まで学ぼう
caseは1つの式に対する一致判定によって処理が分岐される制御構造のひとつです。caseのあとに記述する式とwhen節のあとに記述する各式の値(評価結果)を比較します。
caseは、caseのあとに記述した式とwhen節に記述した式の値(評価結果)を上から順番に比較し、一致すればそのwhen節の本体に記述する処理が実行されます。
1
2
3
4
5
6
7
8
case 式0 #この式の値とwhen節に記述される各式の値が比較される
when 式1 then
# 式0と式1の評価結果が一致した場合の処理(when節本体)
when 式2 then
# 式0と式2の評価結果が一致した場合の処理(when節本体)
else
# どの式とも一致しなかった場合の処理
end
例えば、以下のコードでは対象の式であるbreakfast
の値('ご飯'
)と一致するのは、2番目のwhen節の式の値('ご飯'
)なので'ご飯派です。'
が出力されます。
1
2
3
4
5
6
7
8
9
10
11
breakfast = 'ご飯'
case breakfast #式の値(評価結果)は'ご飯'
when 'パン' then
puts 'パン派です。'
when 'ご飯' then
puts 'ご飯派です。' # このwhen節本体が評価される
else
puts 'パン派でもご飯派でもありません'
end
#=> ご飯派です。
この記事では、caseの使い方を基礎から応用まで段階的に解説しているので、初めての方も1つ1つ整理しながら学ぶことができます。
caseの基本的な使い方
この章では、caseの書き方や処理の流れ、どんな場面で使用すれば良いのかなど基本的な部分を解説します。
基本構文
caseは、以下のようにcase~end
までが範囲になります。
1
2
3
4
5
6
7
8
case 式0
when 式1 then
# 式0と式1の評価結果が一致した場合の処理(when節本体)
when 式2 then
# 式0と式2の評価結果が一致した場合の処理(when節本体)
else
# どの式とも一致しなかった場合の処理
end
case
- 対象の式を記述します。when
- 比較する式、when節本体には一致した際の処理を記述します。else
- どれも一致しなかった場合の処理を記述します。
when 式1 then
とは「式0
と式1
の値が一致する場合にthen
以下の式を評価する」という意味になります。when節、else節のインデントはcaseに揃えます。
※thenは省略することができます。(この章以降はthenを省略します。)
処理の流れ
記事の冒頭では、caseについて下記のように記述しました。
caseは、caseのあとに記述した式とwhen節に記述した式の値(評価結果)を上から順番に比較し、一致すればそのwhen節の本体に記述する処理が実行されます。
この処理の流れをサンプルコードで表すと、以下のような順番になります。
- breakfastの式が評価される。(
'ご飯'
という結果になる) - breakfastの
'ご飯'
と'パン'
を比較する。一致しないので次のwhen節へ - breakfastの
'ご飯'
とwhen節の'ご飯'
を比較する。一致するのでwhen節本体へ - when節本体の式が評価されて、
ご飯派です。
が出力される
上記の「1. breakfastの式が評価される。」とありますが、以下の動画のように式(breakfast)を実行して値を得ることを「評価」といい、値('ご飯')が評価の結果になります。
つまり、caseはcaseの式(breakfast)の評価結果('ご飯'
)とwhen節に記述される各式の値(評価結果)を上から順番に比較して一致するか判定しているのです。
全ての式に一致しない場合
caseの式の値がどのwhen節の式の値にも一致しない場合は、else節に記述した処理が実行されます。
例えばbreakfastに'スムージー'
を代入した場合は、以下の通りになります。
1
2
3
4
5
6
7
8
9
10
11
breakfast = 'スムージー' # ご飯からスムージーへ変更
case breakfast
when 'パン'
puts 'パン派です。'
when 'ご飯'
puts 'ご飯派です。'
else
puts 'パン派でもご飯派でもありません'
end
#=> パン派でもご飯派でもありません
breakfastは、when節の'パン'
にも'ご飯'
にも一致しないのでelse節の処理が実行されて、パン派でもご飯派でもありません
が出力されます。
caseの返り値
caseの返り値は、最後に評価した式の結果を返します。
以下のサンプルコードでは、ハイライトされた'ご飯派です。'
の式が最後に評価される式となり、式の結果がcaseの返り値になります。
1
2
3
4
5
6
7
8
9
10
11
breakfast = 'ご飯'
case breakfast
when 'パン'
'パン派です。'
when 'ご飯'
'ご飯派です。' # caseの返り値になる
else
'パン派でもご飯派でもありません'
end
#=> ご飯派です。
このようにcaseを実行すると式の結果を返り値として得られるので、以下のサンプルコードのようにresult
の変数にcaseを代入して利用することもできます。
1
2
3
4
5
6
7
8
9
10
11
12
breakfast = 'ご飯'
result = case breakfast
when 'パン'
'パン派です。'
when 'ご飯'
'ご飯派です。'
else
'パン派でもご飯派でもありません'
end
puts result #=>ご飯派です。
caseをifに置き換えた場合
caseで記述されたコードは、ifに置き換えることができます。
以下は、caseのサンプルコードです。
1
2
3
4
5
6
7
8
9
10
11
breakfast = 'ご飯'
case breakfast
when 'パン'
puts 'パン派です。'
when 'ご飯'
puts 'ご飯派です。'
else
puts 'パン派でもご飯派でもありません'
end
#=> ご飯派です。
上記のコードをifに置き換えると、以下の通りになります。
1
2
3
4
5
6
7
8
9
10
breakfast = 'ご飯'
if breakfast === 'パン'
puts 'パン派です。'
elsif breakfast === 'ご飯'
puts 'ご飯派です。'
else
puts 'パン派でもご飯派でもありません'
end
#=> ご飯派です。
上記のコードのようにcaseからifへ置き換えることができましが、caseと違ってifの方は各式にbreakfast
を記述して比較させなければいけませんね。
さらにcaseとifのどちらでもこの条件のコードはかけてしまうので「結局どちらを使えば良いのか?」と疑問を持つかと思います。その疑問点は、次の章で解決していきます。
caseを使用する場面とは?
前の章では、caseで記述されたサンプルコードをifに置き換えることができましたね。
どちらを使えば良いか迷うかもしれませんが、1つのデータ(式の評価結果)に対して複数の値をチェックして処理を分けたい場面では、caseを使った方が可読性があがります。
なぜならifの場合は条件式を自由に指定することができるので、いろいろなパターンを想定してコードを読む必要があるからです。例えば、以下のようにbreakfastの値の一致と関係ない条件式が含まれる可能性も考慮する必要があります。
1
2
3
4
5
6
7
8
breakfast = 'ご飯'
if breakfast.empty? # breakfastが空かチェックする
puts '朝食を用意してません'
else
puts '朝食を用意しています。'
end
#=>朝食を用意しています。
上記のようにifを使う場合はbreakfastの値の一致とは関係のない条件式も自由に設定できるので、どんな条件式が設定されているか当たりも付けられず可読性が下がりますね。
しかしcaseの場合は、以下のようにcaseの式と各when節の値が一致するか読むだけでよいのでifに比べてどんな条件式か当たりをつけられて可読性が上がります。
1
2
3
4
5
6
7
8
9
10
11
breakfast = 'ご飯'
case breakfast
when 'パン'
puts 'パン派です。'
when 'ご飯'
puts 'ご飯派です。'
else
puts 'パン派でもご飯派でもありません'
end
#=> ご飯派です。
このように1つのデータに対して複数の値をチェックして処理を分ける場合には、ifではなくcaseを使用するようにしましょう。
case文の応用的な使い方
この章では、基礎から発展したcaseの応用的な使い方や便利な使い方を解説します。
複数の値を指定する方法
when節には、カンマで区切って複数の値(式)を指定することもできます。
1
2
3
4
5
6
7
8
case 式0
when 式1, 式2
# 式0と式1 or 式0と式2の評価結果が一致した場合の処理
when 式3, 式4
# 式0と式3 or 式0と式4の評価結果が一致した場合の処理
else
# どの式とも一致しなかった場合の処理
end
上記のwhen 式1, 式2
は「式0
と式1
の値が一致するか、もしくは式0
と式2
の値が一致する場合」という意味になります。when節の式は上から順に(そして左から順に)式0
と一致するか比較されて、一致した時点でwhen節本体が評価されます。
上記のcaseのコードは、以下のifと大体同じです。
1
2
3
4
5
6
7
if 式1 === 式0 or 式2 === 式0
# 式0と式1 or 式0と式2の評価結果が一致した場合の処理
elsif 式3 === 式0 or 式4 === 式0
# 式0と式3 or 式0と式4の評価結果が一致した場合の処理
else
# どの式とも一致しなかった場合の処理
end
それでは、when節に複数の値を指定する場合をサンプルコードでみていきましょう。
以下のサンプルコードでは、num
の値に対して各when節の値を比較しています。最初のwhen節に複数の値が指定されていますね。
1
2
3
4
5
6
7
8
9
10
11
num = 2
case num
when 1, 2, 3
puts '値は1~3のどれかです。' # このwhen節本体が評価される
when 4
puts '値は4です。'
else
puts '値は1~4ではありません。'
end
#=>値は1~3のどれかです。
処理の流れは、以下の通りです。
- caseに指定したnumの式が評価される。(2という結果になる)
- numの2と最初のwhen節の1が比較される。
- 一致しなかったので、numの2とwhen節の2が比較される。(一致)
- 上記が一致したので、when節本体が評価される(
値は1~3のどれかです。
を出力)
when 1, 2, 3
とありましたがwhen節に複数の値を指定した場合には、左から順番にnum
の値と比較して一致した時点で処理が実行されるので、3
は比較されずにwhen節本体の処理が実行されています。
配列を指定する方法
when節にはwhen *配列
と指定することで配列を使用することができます。
先ほどwhen節に複数の値を指定する方法を解説しましたが、when節に配列を使用することで置き換えることができます。
1
2
3
4
5
6
7
8
9
10
11
num = 2
case num
when 1, 2, 3
puts '値は1~3のどれかです。' # このwhen節本体が評価される
when 4
puts '値は4です。'
else
puts '値は1~4ではありません。'
end
#=>値は1~3のどれかです。
1
2
3
4
5
6
7
8
9
10
11
12
ary = [1,2,3]
num = 2
case num
when *ary
puts '値は1~3のどれかです。'
when 4
puts '値は4です。'
else
puts '値は1~4ではありません。'
end
#=>値は1~3のどれかです。
上記のwhen *ary
のように配列の前に*
をつけることで、配列展開されてnumと比較ができるようになります。
範囲オブジェクトを指定する方法
when節には以下のような範囲オブジェクトを指定することができます。
1
2
1 .. 5 # 1以上5以下(5を含む)
1 ... 5 # 1以上5未満(5を含まない)
例えば各when節に範囲オブジェクトを以下のコードのように指定することで、年齢別に処理を分けることができます。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
age = 6
case age
when 0 .. 2 #0才以上2才以下の者
puts "入場料金は無料です。"
when 3 .. 6 #3才以上6才以下の者
puts "入場料金は500円です。"
when 7 .. 12 #7才以上12才以下の者
puts "入場料金は800円です。"
when 13 .. 18 #13才以上18才以下の者
puts "入場料金は1,500円です。"
else
puts "入場料金は1,800円です。"
end
#=>入場料金は500円です。
age
には6
が代入されているので、入場料金は500円です。
が出力されます。
caseの「式」にメソッドを使用する場合
caseの式には変数だけではなく、メソッドも使用することが出来ます。
メソッドには、以下の文字列の文字数を返すlength
メソッドを使用していきます。
1
2
3
4
irb(main):001:0> str = '私の名前は山田花子です。'
=> "私の名前は山田花子です。"
irb(main):002:0> str.length
=> 12
以下のコードのハイライト部分のように指定することで、str.length
の結果に対して各when節の値を比較することができます。
1
2
3
4
5
6
7
8
9
10
str = '私の名前は山田花子です。'
case str.length
when 1..3
'文字数不足です。'
when 4..10
'設定した文字数の範囲内です。'
when 10..nil # 10以上で上限なし
'文字数オーバーです。'
# => '文字数オーバーです。'
str.length
の結果は12
になるのでwhen 10..nil
の式本体が実行されます。
このようにメソッドを使用することで、メソッドの実行結果でwhen節の値をチェックすることができるので実用性が広がりますね。
case の「式」を省略した場合
caseの式を省略した場合は、以下のコードのようにwhen節の式が偽ではない最初の式が評価されます。when節には2箇所にtrue
を指定していますが、処理が実行されるのは最初のtrue
の方です。
1
2
3
4
5
6
7
8
9
case
when false
puts "falseは偽なので実行されません。"
when true
puts "trueは真なので実行されます。"
when true
puts "trueは真ですが、最初ではないので実行されません。"
end
#=>trueは真なので実行されます。
上記のコードのtrue
やfalse
がイメージしづらいという方は、以下のコードを参考にしてください。
1
2
3
4
5
6
7
8
9
10
11
price = 100
case
when price < 10
puts "式は偽なので実行されません。"
when price == 100
puts "式は真なので実行されます。"
when price == 100
puts "式は真ですが、最初ではないので実行されません。"
end
#=>式は真なので実行されます。
irbで試すとわかりますが、上記のwhen節の式は以下のようにtrue
とfase
をそれぞれ返します。
1
2
3
4
5
6
irb(main):001:0> price = 100
=> 100
irb(main):002:0> price < 10
=> false
irb(main):003:0> price == 100
=> true
caseを省略した場合は、when節の偽ではない最初の式が評価されるのでハイライトされているprice == 100
の式本体が実行されるのです。
1
2
3
4
5
6
7
8
9
10
11
price = 100
case
when price < 10
puts "式は偽なので実行されません。"
when price == 100
puts "式は真なので実行されます。"
when price == 100
puts "式は真ですが、最初ではないので実行されません。"
end
#=>式は真なので実行されます。
classによって処理を変える方法
when節には、以下のコードのようにclassを指定することもできます。
1
2
3
4
5
6
7
8
9
10
11
12
13
obj = [1,2,3]
case obj
when String
puts 'classはStringです。'
when Array
puts 'classはArrayです。'
when Hash
puts 'classはHashです。'
else
puts 'classはString、Array、Hash以外です。'
end
#=>classはArrayです。
classによって実行する処理を変えたい場合に便利ですね。
制御構造の条件分岐まとめ
Rubyの条件分岐は、以下の表の通りです。
条件分岐 | 説明 | リンク |
---|---|---|
case | 1つの式に対する一致判定によって処理が分岐される | |
if | 真偽値で条件を分岐することができる (真の時にthen以下の式を評価) |
ifの使い方 |
unless | 真偽値で条件を分岐することができる (偽の時にthen以下の式を評価) |
unlessの使い方 |
Rubyの制御構造の条件分岐について、もっと深く理解したい方はこちらの参考書で学びましょう。
この記事のまとめ
- caseは1つの式に対する一致判定によって処理が分岐される
- caseの式とwhen節の式の評価結果が一致すると、when節本体の処理が実行される
- どの式にも一致しない場合は、else節の処理が実行される