【Swift入門 #14】複数の選択肢 - switch文の強力なパターンマッチ

複数の条件分岐を美しく書けるswitch文について、Swiftならではの強力なパターンマッチング機能を初心者向けに解説します。

📚 Swift入門シリーズ: #12 for-inループ#13 if文


前回はif文による条件分岐を学びました。今回は、複数の選択肢を扱うのに適したswitch文について学びましょう。

著者
著者: Sera
大学院でAI作曲に関して研究中!
来春からデータサイエンティストとして働く予定の技術オタク。
初心者
登場人物: あかり
流行りのAIやWeb技術に興味津々!
『知りたい』気持ちで質問を止められない、好奇心旺盛な学生。
normalの表情
初心者

前回はif文で条件分岐を学んだね!でも、選択肢がたくさんあるとelse ifが長くなって読みにくくなりそう...

専門家

その通り!そういう場合に便利なのが switch文 なんだ。複数の選択肢をスッキリ書けるんだよ。

excitedの表情
初心者

便利そう!教えて!

switch文の基本

専門家

switch文 の基本的な書き方はこうなるよ。

switch 値 {
case パターン1:
    // パターン1にマッチしたときの処理
case パターン2:
    // パターン2にマッチしたときの処理
default:
    // どのパターンにもマッチしなかったときの処理
}

実際の例を見てみよう。

let fruit = "りんご"

switch fruit {
case "りんご":
    print("赤い果物です")
case "バナナ":
    print("黄色い果物です")
case "オレンジ":
    print("オレンジ色の果物です")
default:
    print("知らない果物です")
}
// 赤い果物です

値がどのcaseにマッチするかをチェックして、マッチしたcaseの処理を実行するんだ。

confusedの表情
初心者

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文の方が、構造が見やすくて読みやすいよね。

happyの表情
初心者

確かに!スッキリしてる!

複数の値をまとめて扱う

専門家

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("不正な点数")
}
// 優

範囲を使えば、数値の判定がとても見やすく書けるんだよ。

excitedの表情
初心者

これは便利!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」という意味になるんだよ。

surprisedの表情
初心者

複雑な条件も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が等しい場合」という追加条件を指定しているんだ。

confusedの表情
初心者

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文を書いてみて。

excitedの表情
初心者

やってみる!

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文を書いてみて。

normalの表情
初心者

えーと...タプルと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ループについて学びます。条件に基づいた繰り返し処理をマスターしましょう!

← ブログ一覧に戻る