Swift
for文
swift3

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

More than 1 year has passed since last update.

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文をナウい形に書き換える際は、注意しておきたい。