📚 Swift入門シリーズ: #12 for-inループ → #13 if文
前回はif文による条件分岐を学びました。今回は、複数の選択肢を扱うのに適したswitch文について学びましょう。
来春からデータサイエンティストとして働く予定の技術オタク。
『知りたい』気持ちで質問を止められない、好奇心旺盛な学生。
前回はif文で条件分岐を学んだね!でも、選択肢がたくさんあるとelse ifが長くなって読みにくくなりそう...
その通り!そういう場合に便利なのが switch文 なんだ。複数の選択肢をスッキリ書けるんだよ。
便利そう!教えて!
switch文の基本
switch文 の基本的な書き方はこうなるよ。
switch 値 {
case パターン1:
// パターン1にマッチしたときの処理
case パターン2:
// パターン2にマッチしたときの処理
default:
// どのパターンにもマッチしなかったときの処理
}
実際の例を見てみよう。
let fruit = "りんご"
switch fruit {
case "りんご":
print("赤い果物です")
case "バナナ":
print("黄色い果物です")
case "オレンジ":
print("オレンジ色の果物です")
default:
print("知らない果物です")
}
// 赤い果物です
値がどのcaseにマッチするかをチェックして、マッチしたcaseの処理を実行するんだ。
defaultって何?必ず書かなきゃダメ?
default は、どのcaseにもマッチしなかったときの処理なんだ。Swiftのswitch文は 網羅的(exhaustive) でなければならないというルールがあって、すべての可能性をカバーする必要があるんだよ。
だから、すべてのケースをcaseで書いていない場合は、defaultが必要になるんだ。
let number = 5
switch number {
case 1:
print("1です")
case 2:
print("2です")
// default: // これがないとエラー
// print("それ以外です")
}
// エラー:Switch must be exhaustive
でも、すべてのケースをcaseでカバーしている場合は、defaultは不要なんだよ。これは後で見る列挙型のところで詳しく説明するね。
if文とswitch文の比較
if文とswitch文を比較してみよう。
if文での書き方:
let grade = "B"
if grade == "A" {
print("優秀です")
} else if grade == "B" {
print("良好です")
} else if grade == "C" {
print("普通です")
} else {
print("要改善です")
}
switch文での書き方:
let grade = "B"
switch grade {
case "A":
print("優秀です")
case "B":
print("良好です")
case "C":
print("普通です")
default:
print("要改善です")
}
switch文の方が、構造が見やすくて読みやすいよね。
確かに!スッキリしてる!
複数の値をまとめて扱う
Swiftのswitch文では、複数の値を1つのcaseでまとめて扱えるんだ。カンマで区切るだけなんだよ。
let fruit = "バナナ"
switch fruit {
case "りんご", "いちご", "さくらんぼ":
print("赤系の果物です")
case "バナナ", "レモン":
print("黄色系の果物です")
case "オレンジ", "みかん":
print("オレンジ系の果物です")
default:
print("その他の果物です")
}
// 黄色系の果物です
これで、複数の値に対して同じ処理を実行できるんだ。
範囲でのマッチング
Swiftのswitch文は、範囲演算子を使った強力なパターンマッチングができるんだ。
let score = 85
switch score {
case 0..<60:
print("不合格")
case 60..<70:
print("可")
case 70..<80:
print("良")
case 80..<90:
print("優")
case 90...100:
print("秀")
default:
print("不正な点数")
}
// 優
範囲を使えば、数値の判定がとても見やすく書けるんだよ。
これは便利!if文だとelse ifがたくさん必要だったよね!
タプルのマッチング
Swiftのswitch文では、タプルもマッチングできるんだ。これがとても強力なんだよ。
let point = (x: 0, y: 0)
switch point {
case (0, 0):
print("原点です")
case (_, 0):
print("x軸上にあります")
case (0, _):
print("y軸上にあります")
case (-2...2, -2...2):
print("四角形の内部にあります")
default:
print("四角形の外部にあります")
}
// 原点です
_(アンダースコア)は「どんな値でもマッチする」という意味なんだ。(_, 0) は「xは何でも良くて、yが0」という意味になるんだよ。
複雑な条件も1つのswitch文で書けるんだね!
値の束縛(Value Binding)
switch文では、マッチした値を変数に束縛して使うこともできるんだ。
let point = (x: 2, y: 0)
switch point {
case (0, 0):
print("原点です")
case (let x, 0):
print("x軸上の点(\(x), 0)です")
case (0, let y):
print("y軸上の点(0, \(y))です")
case (let x, let y):
print("点(\(x), \(y))です")
}
// x軸上の点(2, 0)です
let x でマッチした値を変数xに束縛して、そのブロック内で使えるようになるんだ。
もっと短く書くこともできるよ。
let point = (x: 3, y: 4)
switch point {
case (0, 0):
print("原点です")
case let (x, 0):
print("x軸上の点(\(x), 0)です")
case let (0, y):
print("y軸上の点(0, \(y))です")
case let (x, y):
print("点(\(x), \(y))です")
}
// 点(3, 4)です
let をタプルの前に書くと、すべての値が束縛されるんだ。
where句による追加条件
where句 を使えば、caseにさらに条件を追加できるんだ。
let point = (x: 1, y: 1)
switch point {
case (0, 0):
print("原点です")
case let (x, y) where x == y:
print("y = x の直線上にあります")
case let (x, y) where x == -y:
print("y = -x の直線上にあります")
case let (x, y):
print("点(\(x), \(y))です")
}
// y = x の直線上にあります
where x == y で「xとyが等しい場合」という追加条件を指定しているんだ。
whereって便利だね!でもいつ使えばいいの?
where句は、パターンマッチングだけでは表現できない複雑な条件を追加したいときに使うんだ。
let age = 25
let hasLicense = true
switch (age, hasLicense) {
case let (a, true) where a >= 18:
print("運転できます")
case (_, true):
print("年齢が足りません")
case (_, false):
print("免許がありません")
}
// 運転できます
こういった複合的な条件を、switch文の中で美しく表現できるんだよ。
実践練習
じゃあ、練習問題をやってみよう。
問題1: 曜日を表す数値(1=月曜、2=火曜...7=日曜)を受け取って、「平日」または「週末」と表示するswitch文を書いてみて。
やってみる!
let dayOfWeek = 3
switch dayOfWeek {
case 1, 2, 3, 4, 5:
print("平日")
case 6, 7:
print("週末")
default:
print("不正な値")
}
// 平日
できた!
完璧だね!複数の値をカンマで区切って1つのcaseにまとめているね。範囲を使うこともできるよ。
let dayOfWeek = 3
switch dayOfWeek {
case 1...5:
print("平日")
case 6...7:
print("週末")
default:
print("不正な値")
}
問題2: 2つの数値を受け取って、「両方正」「両方負」「符号が違う」「少なくとも1つは0」と判定するswitch文を書いてみて。
えーと...タプルとwhereを使えばいいのかな?
let a = 5
let b = -3
switch (a, b) {
case (0, _), (_, 0):
print("少なくとも1つは0")
case let (x, y) where x > 0 && y > 0:
print("両方正")
case let (x, y) where x < 0 && y < 0:
print("両方負")
default:
print("符号が違う")
}
// 符号が違う
こう?
素晴らしい!タプルとwhereを使いこなせているね。順序も正しいよ。0のケースを最初にチェックしているのがいいね。switch文をしっかり理解できているよ。
まとめ
この記事では、switch文について学びました。
switch文の基本:
switch 値 { case パターン: 処理 }- すべてのケースをカバーする必要がある(網羅的)
- 自動的にbreakされる
強力なパターンマッチング:
- 複数の値:
case 1, 2, 3: - 範囲:
case 0..<60: - タプル:
case (0, 0): - ワイルドカード:
case (_, 0):
高度な機能:
- 値の束縛:
case let (x, y): - where句:
case let (x, y) where x == y:
if文との使い分け:
- 2-3個の選択肢:if-else
- 多数の選択肢:switch
- 複雑なパターンマッチング:switch
次回は「繰り返し処理」として、whileループについて学びます。条件に基づいた繰り返し処理をマスターしましょう!