Codable Tech Blog

iPhoneアプリケーション開発と AWS(Amazon Web Service)活用に関する記事を配信

switch文

switch文

if文を利用した場合分けの処理の中で、変数がどの値とマッチしているかを判断して処理を切り分けることがよく行われます。次のif文はnumの値がある値とマッチしていれば、printlnで文字列を出力し、いずれもマッチしなければ、マッチしなかった旨を出力します。

var num = 20
if num == 10{
    print("10と一致")
} else if num == 20 {
    print("20と一致")
} else if num == 30 {
    print("30と一致")
} else if num == 40 {
    print("40と一致")
} else {
    print("上記以外")
}

//結果
//20と一致

値のマッチングによる分岐処理をif-else if-else文で記述しても問題ありませんがswitch文を利用することでより読みやすいコードを記述することが可能になります。
switch文の書式は以下の通りです。

switch 式 {
case パターン1:1
case パターン2:2
default:3
}

switch文ではマッチング対象の式とcase句に記述されているパターンの比較を行い、最初にマッチした箇所のcase句の処理が実行されます。また、switch文は網羅的である必要があります。これはswitch文で値の比較を行った時、必ずいずれかの文が実行されなければいけないということです。このため、switch文ではdefault句が用意されており、case句に記述したいずれの条件とも合致しない場合はdefault句の処理が実行されます。default句はswitchの末尾に書きます。先ほど記述したif-else if-else文をswitch文で書き直すと以下のようになります。

var num = 20
switch num {
case 10:
    print("10と一致")
case 20:
    print("20と一致")
case 30:
    print("30と一致")
case 40:
    print("40と一致")
default:
    print("それ以外")
}


//結果
//20と一致

numの値が20ですので、case 20とマッチします。そして、case 20:句の処理が実行されます。swiftのswitch文は1つのcaseを実行した後、switch文のブロックを抜けますので今回の例では「20と一致」という文言を出力してswitch文を抜けます。

case句の注意点

それぞれのcaseは実行コードを1つは含んでいないといけません。次の例は不正な記述です。なぜなら最初のケース(case num 10:)に実行コードが記述されていないからです。

var num = 20
switch num {
case 10:
case 20:
    print("10または20と一致")
case 30:
    print("30と一致")
case 40:
    print("40と一致")
default:
    print("それ以外")
}

もし、複数のケースで同じ処理を行いたい場合はカンマ区切りで値を並べましょう。

var num = 20
switch num {
case 10,20:
    print("10または20と一致")
case 30:
    print("30と一致")
case 40:
    print("40と一致")
default:
    print("それ以外")
}

//結果
//10または20と一致

このように記述した場合、numの値が10もしくは20の場合は「 10または20と一致」という文字列が出力されます。

範囲マッチング

switch文では単独の値の比較だけではなく、ある値が特定の範囲内に収まっているかどうかも判定できます。if文ではand演算子を用いて特定の範囲内かどうかを判定する処理が記述できますがswitch文では範囲演算子を利用してより簡潔に表現することができます。

範囲演算子

swiftで範囲を表現したい時は範囲演算子を利用します。

演算子 説明
a...b aからbまで。aはbより小さい値でなければならない。
a..<b aからb-1まで。aはbより小さい値でなければならない。

この範囲演算子を活用することで、範囲による場合分け処理を簡潔に記述できます。switch文を利用した範囲による場合分け処理は以下のように記述できます。

var count = 55
switch count {
case 0...10:
    print("0以上10以下")
case 11...30:
    print("11以上30以下")
case 31...60:
    print("31以上60以下")
case 61...100:
    print("61以上100以下")
default:
    print("上記以外")
}

//結果
//31以上60以下

この例では範囲演算子...を利用してnumの値がどの範囲に含まれるかを判断しています。numの値が0から10の間であれば、case 0...10:句の処理が実行されますし、numの値が11から30の間であれば、case 11...30:句の処理が実行されます。今回はnumの値は55なのでcase 31...60:句の処理が実行されます。

タプルのマッチング

switch文ではタプルのマッチング判定を行うことも可能です。タプルのそれぞれの要素に対して、値もしくは範囲指定によるマッチングを行うことができます。もし、全ての値と合致させたい場合は_を使います。_は「ワイルドカードパターン」と呼ばれる識別子で全ての値とマッチングする特別な識別子です。

let nTaple = (1, 1)
switch nTaple {
case (0, 0):
    print("(0, 0)")
case (_, 0):
    print("(_, 0)")
case (0, _):
    print("(0, _)")
case (-2...2, -2...2):
    print("(-2から2,-2から2)")
default:
    print("上記以外")
}
//結果
//(-2から2,-2から2)

case (0, 0)は1番目の要素が0、2番目の要素が0の時、マッチするcase句になります。case (_, 0)は1番目の要素は不問なので、2番目の要素が0であれば、マッチするcase句になります。case (0, _)は2番目の要素は不問なので、1番目の要素が0であれば、マッチするcase句になります。case (-2...2, -2...2)は1番目の要素が-2から2の範囲、2番目の要素が-2から2の範囲の時、マッチするcase句になります。今回のケースではnTapleが(1, 1)なのでcase (-2...2, -2...2)に合致します。
このため、case (-2...2, -2...2)の文が出力されます。

バリューバインディング(Value Binding)

switch文ではマッチした値をcase句の中で変数や定数として利用することができます。このように外部で定義された値を取り込むことをバリューバインディングと呼びます。次の例では、switch文の外で定義されたnTapleの値をswitchブロックの中に取り込んでいます。

let nTaple = (2, 0)
switch nTaple {
case (let x, 0):
    print("(x,0) xに2が代入されている")
case (0, let y):
    print("(0,y) yに0が代入されている")
case let (x, y):
    print("(x,y) xに2,yに0が代入されている")
}

//結果
//(x,0) xに2が代入されている

case (let x, 0)は2番目の要素が0だった場合に合致するcase句です。この条件に合致した場合、バリューバインディングを利用してnTapleの1番目の要素の値を定数xとして取り込みます。
case (0, let y)は1番目の要素が0だった場合に合致するcase句です。この条件に合致した場合、バリューバインディングを利用してnTapleの2番目の要素の値を定数yとして取り込みます。
case let (x, y)はどの条件でも合致するcase句です。このため、このswitch文ではdefault句が不要です。この場合、nTapleの1番目の要素の値を定数x、2番目の要素の値を定数yとして取り込みます。今回の例ではcase句の中で値を変更しないのでletを使用してますがcase句の中で値を変更したい場合はvarを利用します。バリューバインディングで取り込んだ変数および定数はswitch文の中でだけ有効であることに注意してください。

where句

バリューバインディングによって取り込んだ値を利用した条件式をwhere句で記述することが可能です。
構文は以下の通りです。

switch 式 {
case パターン1 where 条件式1:1
case パターン2 where 条件式2:2
default:3
}

次の例はバリューバインディングを利用してswitchブロックに値を取り込み、取り込んだ値をwhere句を使用して条件判定するswitch文です。

let nTaple = (1, -1)
switch nTaple {
case let (x, y) where x == y:
    print("xとyが等しい")
case let (x, y) where x == -y:
    print("xと-yが等しい")
case let (x, y):
    print("上記以外")
}
//結果
//xと-yが等しい

case let (x, y) where x == yは1番目の要素と2番目の要素が同じ場合に合致するcase句です。
case let (x, y) where x == -yは1番目の要素が2番目の要素に-1を掛けた数と同じである場合に合致するcase句です。case let (x, y)はどの条件でも合致するcase句です。この場合、nTableが(1, -1)ですので、case let (x, y) where x == -yに該当します。このようにバリューバインディングで取り込んだ値とwhere句を利用することで取り込んだ値に対する条件式を記述することが可能になります。