SwiftのFor-in文

For文

繰り返し処理を「ループ」と呼びますが、Swiftでは大きく分けてfor-in文とwhile文が用意されています。基本的にはどちらも似たような処理ができます。ものすごくおおざっぱに分けると、ちょっとした繰り返しやループ回数が決まっている処理ならfor-in文、繰り返し処理の回数が前もって分からないけどループを回したい場合はwhile文です。

Swift 2.1までは、C言語のようなfor文が使えました。しかしながら、Swift 2.2からは非推奨となり、Swift 3以降完全に削除されています。したがって、これから紹介するfor-in文を使っていくことを強くオススメします。

Swift 2.x系では一応使えますがwarningが出て、

//warning: C-style for statement is deprecated and will be removed in a future version of Swift

Swift 3ではコンパイルエラーとなります。

//error: C-style for statement has been removed in Swift 3

For-inの基本的な構文

for-inループは、例えばコレクション型(Arraysなど)の中身を順番に処理したい場合に使える構文です。

// 配列(Array)要素を順番に表示
var kyushu = ["福岡","佐賀","長崎","熊本","大分","宮崎","鹿児島"]
for element in kyushu {
  print("\(element)県です")
}
// 福岡県です
// 佐賀県です
// 長崎県です
// 熊本県です
// 大分県です
// 宮崎県です
// 鹿児島県です

いきなり例文から入りましたが、基本的なfor-inループの構造は

// for-inループ
for constantName in condition {
  statements
}

となっています。constantNameというのは、ループ内で使用するローカル定数です。conditionから渡される値が格納される一時的な定数です。

conditionは、ループをどう回すのかという条件を指定する部分です。上記の例では、Array本体kyushuが指定されていますが、この場合「kyushuの要素を順番に全て処理する」という条件になります。

したがって、最初の例を少し回りくどい日本語で書くと

  1. 最初の配列要素kyushu[0]elementに代入
  2. statementsで処理。ここではprint()で表示
  3. ループの先頭に戻り、次の配列要素kyushu[1]elementに代入
  4. statementsで処理

という具合になります。このループが、配列要素を全部処理するまで続きます。また、連想配列である辞書コレクション型(Dictionary)の各要素へアクセスすることも可能です。

ループ内のローカル定数、ループのスコープ

範囲演算子を使ってループを回すことも可能です。

// 範囲演算子でfor-inループ
for id in 1...3 {
  print("indexは\(id)です。")
}
// indexは1です。
// indexは2です。
// indexは3です。

この例では、1から3の整数(1, 2, 3)を順番に処理しています。

for-inループの構造を説明する際にさらっと流しましたが、idはローカル定数(for-inループ内でのみ有効な定数)ですのでループ外では使用できません。

// for-inループのスコープ
for id in 1...3 {
  print("indexは\(id)です。")
} // for-inループはここまで

// ループの外
print("\(id)")
// Xcodeのエラー: error: use of unresolved identifier 'id' print("\(id)")

一番最初の例のelementも同様です。公式マニュアルに記載があるように、Swiftではfor-inループで使う値を自動的に定数として生成します。

“In the example above, index is a constant whose value is automatically set at the start of each iteration of the loop. As such, index does not have to be declared before it is used. It is implicitly declared simply by its inclusion in the loop declaration, without the need for a let declaration keyword.”

抜粋:: Apple Inc. “The Swift Programming Language”。 iBooks https://itun.es/jp/jEUH0.l

したがって、ループ内で値を変更することもできません。

// ローカル定数の変更はできない
for id in 1...3 {
  print("indexは\(id)です。")
  id += 1 // エラー:error: left side of mutating operator isn't mutable: 'id' is a 'let' constant
}

ループの外に結果を持ち出すには?

時にはループ内の評価結果を外に持ち出したいことがあります。その場合、ループを始める前に変数を宣言しておけば問題ありません。

// ループ内の計算を外に出す場合
var result = 0
for id in 1...3 {
  print("indexは\(id)です。")
  result += id*id
}
print("1^2 + 2^2 + 3^2 = \(result)")
// "1^2 + 2^2 + 3^2 = 14"と表示

また、ループ内でローカル定数を必要としない場合、アンダースコア_を指定します。

// ローカル定数が必要ない場合
var result = 0
let value = 10
for _ in 1...3 {
  result += value*value
}
print("結果:\(result)")
// "結果:300"と表示

まとめ

  • 前もってループさせる回数が決まっている場合はfor-in文
  • コレクション型の各要素をまとめて処理したい場合もfor-in文
  • for-in文で使う値は「ローカル」定数。したがって、それをループの外には持ち出せない