Cスタイルのfor文をSwift3で書き換えるときにハマるパターン

  • 3
    いいね
  • 2
    コメント

Swift3より前に書いたCスタイルのfor文
for 初期設定; 実行条件; インクリメント
をSwift3以降で
for i in 範囲
に変換するときにハマるパターンがあります。

入れ物がいくつかある。
左からいくつかは丸が入っている。
Base.png
残りの入れ物に三角を入れる処理を行いたい。
Umed.png
丸が入っている最終の入れ物のindexをcurrentPosとし、
最後の入れ物のindexをendPosとする。
Umed With String.png
三角を入れる処理のfor文は、Cスタイルの書き方では

for var i = currentPos + 1; i<=endPos; i += 1 {
    //ポジションiに三角を入れる処理
} 

と書ける。
この書き方を範囲指定の書き方に置き換えると

for i in (currentPos + 1)...endPos {
    //ポジションiに三角を入れる処理
}

となる。

ところが次のように初めから全ての入れ物に丸が入っていた場合、上の範囲指定の書き方ではうまくいかない。
Full.png
この場合、範囲 (currentPos + 1)...endPos5...4 となって実行時エラーになる。範囲の指定は...方式でも..<方式でも、右より左の方が大きいと実行時エラーで落ちる。

Cスタイルの書き方では初期設定と実行条件を与えれば、あとは自動でうまくやってくれますが、Swiftでは範囲の生成がうまく出来ないと実行時エラーになってしまうので注意。

対策は
stride(from: , through: , by: )
を使うことです。throughの値よりもfromの値の方が大きい場合でも、何も実行せずに次の命令に移るだけなのでCスタイルで書くのと同じノリでいけます。
例に上げたやり方だと初期値は1大きいだけなので
(currentPos + 1)..<(endPos + 1)
でも対応できます。

また、dropFirst()を使う方法もあります。

for i in (0...endPos).dropFirst(currentPos + 1) {
}

で可能です。(コメントで指摘してもらったやり方)

Cスタイルのfor文をナウい形に書き換える際は、注意しておきたい。