Help us understand the problem. What is going on with this article?

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

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

samekard
アウトドアプログラミング初心者 コンパイルエラー寄せ集め https://samekard.blogspot.jp/2014/09/swifterror.html
https://samekard.jp/ja/index.html
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away