7. 条件判断
今まで見てきたように、一般的にプログラムは書かれている順番に(上から下に)一行ずつ実行されていきます。
しかしこれでは、「特定の場合にのみ実行したい」、「この部分を繰り返して実行したい」といった場合に困ってしまいます。
そこで使われるのが「制御構造」と呼ばれる仕組みです。
条件判断
プログラムは基本的にコードを上の行から一文ずつ実行していきますが、「数値が10より小さい場合だけ処理したい」などの条件によってその後の処理を分けたい場合もあります。
条件判断を使用することで、以下のような場合分けが実現出来ます。
1
2
3
4
5
6
7
8
9
10
11
num = 2
if num < 10
# 条件が真(true)のときの処理
puts "nは10より小さい"
else
# 条件が偽(false)のときの処理
puts "nは10より大きい"
end
#=> nは10より小さい
比較演算子
真偽条件に使う演算子は次のようなものがあります。
比較演算子 | trueとなる条件 | 例 | |
---|---|---|---|
a == b |
a と bの値が等しい | a == 100 | a が 100 のとき true |
a != b |
a と bの値が異なる | a != 100 | a が 100 以外のとき true |
a < b |
a が bより小さい | a < 100 | a が 100より小さいとき true |
a > b |
a が bより大きい | a > 100 | a が 100より大きいとき true |
a <= b |
a が b以下 | a <= 100 | a が 100以下のとき true |
a >= b |
a が b以上 | a >= 100 | a が 100以上のとき true |
論理演算子
複数の条件を組み合わせたり、条件を反転させるときに使います。
論理演算子 | 意味 | true となる条件 |
---|---|---|
条件1 && 条件2 |
条件1 かつ 条件2 | 条件1 と 条件2 がともに真 |
条件1 || 条件2 |
条件1 または 条件2 | 条件1 または 条件2 のどちらかが真 |
! 条件 |
条件 でない | 条件 が偽のとき |
1
2
3
4
5
6
7
8
9
num = 18
if 10 <= num && num < 100
puts "#{num}は二桁の正の数です"
else
puts "#{num}は二桁の正の数ではありません"
end
#=> 18は二桁の正の数です
条件文(if・unless)
条件によって処理を変える際には
「ある条件の時~したい」/「ある条件の時~したくない」というケースがあります。
前者の場合はif
、後者の場合はunless
を用います。
まずは例を見てみましょう。
以下は、変数num
に指定された数値が0の場合「numは0です」、数値が0以外の場合「numは0ではありません」と表示するものです。
num
の値を変えて試してみましょう。
1
2
3
4
5
6
7
8
9
10
11
12
13
num = 0
# 数値が0の場合「numは0です」と表示したい
if num == 0
puts "numは0です"
end
# 数値が0でないとき「numは0ではありません」と表示したい
unless num == 0
puts "numは0ではありません"
end
#=> numは0です
if
とunless
は、読みやすさを重視して使い分けてください。
それぞれ詳しく見ていきましょう。
ある条件の時~したい: if
前述のとおり、主に「ある条件の時~したい」際に使用します。
1
2
3
if condition
# 条件が真のときの処理
end
次の例は、数値が奇数か偶数かを判断して文字を出力します。
1
2
3
4
5
6
7
8
9
num = 20
if num % 2 == 0
puts "偶数です。" #=>numが偶数のとき
else
puts "奇数です。" #=>numが奇数のとき
end
#=> 偶数です
上記の例のように、
評価式が真である場合(if
)と偽である場合(else
)とで処理を分けたい場合、以下のように記述します。
1
2
3
4
5
if condition # 条件
# 条件が真であるときの処理
else
# 条件が偽であるとき処理
end
また、複数の条件を段階的に設定したい場合は、elsif
を使いましょう。
1
2
3
4
5
6
7
8
9
10
11
num = 1
if num == 0
puts "0です" #=>numが0のとき
elsif num >= 1
puts "正の数です" #=>numが1以上のとき
else
puts "負の数です" #=>numが0より小さいとき
end
#=> 正の数です
まとめるとこのようになります
1
2
3
4
5
6
7
8
9
if condition1 # 条件1
# 条件1が真であるのときの処理
elsif condition2 # 条件2
# 評価2が真であるのときの処理(条件1は偽)
elsif condition3 # 条件3
# ...
else
# 条件1,条件2,…が偽でないときの処理
end
ある条件でない時~したい: unless
unless
は、評価式が偽のとき処理を実行します。
1
2
3
unless condition # 条件
# 条件が偽であるときの処理
end
if
で記述して読みづらいと感じたときは、unless
で書いてみることも考えてみてください。
1
2
3
4
5
6
7
8
9
10
11
12
text = "hoge"
if !(text == "")
puts "textは空文字ではありません"
end
#=> textは空文字ではありません
# すっきりする
unless text == ""
puts "textは空文字ではありません"
end
#=> textは空文字ではありません
unless
におけるelse
以下の処理は、評価式が偽でないとき(=真であるとき)に実行します。
1
2
3
4
5
unless condition # 条件
# 条件が偽であるときの処理
else
# 条件が偽でないときの処理 = 真であるときの処理
end
しかし、この書き方はあまり推奨されていません。
unless
が「条件を満たさない場合」、else
が「条件を満たさない場合じゃない場合」という意味になり、とても分かりづらいからです。
この場合、if ~ else ~ end
で置き換えましょう。
参考:コーディング規約
また、unless
文はif
文と異なり、elsif
にあたるものはないので注意しましょう。
case文
ある1つの変数に対して、複数の候補値によって処理を分けたい場合、case
文が有効です。
1
2
3
4
5
6
7
8
9
10
case var
when value1
# varが値1のときの処理
when value2
# varが値2のときの処理
when value3
# varが値3のときの処理
else
# どの値にも一致しないときの処理
end
例えば、以下のような、if
で書かれた条件判断があるとします。
1
2
3
4
5
6
7
8
9
10
11
12
13
num = 2
if num == 0
puts "numは0です。"
elsif num == 1
puts "numは1です。"
elsif num == 2
puts "numは2です。"
else
puts "numはどの条件にも当てはまりません。"
end
#=>numは2です。
num
が何回も出てきて、見づらいですね。
1つのnum
に対して、複数の候補(0,1,2,その他)から一致する条件を探しているパターンです。
上記のものを、case
文に書き換えてみましょう。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
num = 2
case num
when 0
puts "numは0です。"
when 1
puts "numは1です。"
when 2
puts "numは2です。"
else
puts "numはどの条件にも当てはまりません。"
end
#=>numは2です。
文字数も少なく、とてもすっきりしました。
「同じnum
を評価している」ということがぱっと見で分かりやすいですね。
範囲式
case
文のwhen
句には、範囲を指定することも出来ます。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
num = 2
case num
when 1..9
puts "numは一桁の正の数です。"
when 10..99
puts "numは二桁の正の数です。"
when 100..999
puts "numは三桁の正の数です。"
else
puts "numはどの条件にも当てはまりません。"
end
#=>numは一桁の正の数です。
真と偽
さて、ここまでに「真」「偽」という記述とtrue
・false
という記述があったと思います。
一見するとこの二つは同じもののようですが、実はRubyにおける真/偽の概念はtrue
・false
と一対一で結びついているわけではありません。
偽に該当するのはfalse
とnil
の二つで、その他のオブジェクトはすべて真となります。
真偽 | オブジェクト |
---|---|
真 | false と nil を除くすべて |
偽 | false と nil |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
objects = [
[], # Arrayクラス
{}, # Hashクラス
"", # Stringクラス
0, # Numericクラス
true, # Trueクラス
false, # Falseクラス
nil # Nilクラス
]
objects.each do |object|
p object
if object
puts "=> 真"
else
puts "=> 偽"
end
end
# []
# => 真
# {}
# => 真
# ""
# => 真
# 0
# => 真
# true
# => 真
# false
# => 偽
# nil
# => 偽
Step Up! : 式修飾子 (後置 if・unless)
if
文やunless
文を一行で記述する方法で、else
を必要としない場合に使用することが多いです。
1
2
process if condition
process unless condition
例:
1
2
3
4
a = 0
b = 1
puts "aは0です。" if a == 0 #=> aは0です。
puts "bは0です。" if b == 0 #=> (表示されない)
Step Up! : 条件演算子(三項演算子)
if ... else ...
の場合も一行で記述できる方法があります。
1
condition ? value_for_true : value_for_false
例:
1
2
3
4
a = 10
b = -5
puts a >= 0 ? a : -a #=> 10
puts b >= 0 ? b : -b #=> 5
三項演算子を用いることでシンプルに書ける場合は使ってみましょう。
ただし、複雑な分岐になるほど三項演算子は可読性が低くなってしまいますので注意が必要です。
演習問題
問1
指定した数値num
が3で割り切れるか判定し、以下のような出力をする条件分岐を作成して下さい。
1
2
3
4
5
num = 15
#=> 15は3で割り切れます
num = 7
#=> 7は3で割り切れません
問2
おにぎり(100円), お茶(150円), 弁当(500円)があります。
所持金money
を入力したとき、その所持金で購入可能な商品の一覧を出力させてください。
1
2
3
4
5
6
7
8
9
10
# money = 200 の場合
#=> 購入可能な商品 : おにぎり, お茶
# money = 0 の場合
money = 0
#=> 購入可能な商品 :
# money = 500 の場合
money = 500
#=> 購入可能な商品 : おにぎり, お茶, 弁当
※いろいろな書き方が考えられます。時間があったら考えてみましょう。