【Swift入門 #12】コレクションを使いこなす - for-inループで反復処理

配列、辞書、セットを効率的に処理するfor-inループについて、その使い方と実践的なテクニックを初心者向けに解説します。

📚 Swift入門シリーズ: #10 辞書Dictionary#11 セットSet


これまで学んだ配列、辞書、セットのすべての要素を処理したいとき、for-inループが非常に便利です。この記事では、反復処理の基本と応用を学びましょう。

著者
著者: Sera
大学院でAI作曲に関して研究中!
来春からデータサイエンティストとして働く予定の技術オタク。
初心者
登場人物: あかり
流行りのAIやWeb技術に興味津々!
『知りたい』気持ちで質問を止められない、好奇心旺盛な学生。
normalの表情
初心者

前回はセットSetで重複のないデータを扱う方法を学んだね!

専門家

そうだね。第3章でコレクション型を学んできたね。今回は、それらのコレクションを効率的に処理する方法を学んでいくよ。

excitedの表情
初心者

配列、辞書、セット...3つのコレクション型を学んできたね!

専門家

そうだね。今回は、それらのコレクションを効率的に処理する方法を学んでいくよ。

confusedの表情
初心者

配列の全部の要素に同じ処理をしたいとき、一つ一つ書くしかないの?

専門家

いや、そんなことはないよ!for-inループ を使えば、コレクションのすべての要素に対して、同じ処理を簡単に実行できるんだ。

excitedの表情
初心者

便利そう!教えて!

for-inループの基本

専門家

for-inループ は、コレクション(配列、辞書、セットなど)の要素を1つずつ取り出して処理する構文なんだ。基本的な書き方はこうなるよ。

for 要素 in コレクション {
    // 処理
}

実際の例を見てみよう。

let fruits = ["りんご", "バナナ", "オレンジ"]

for fruit in fruits {
    print(fruit)
}
// りんご
// バナナ
// オレンジ

for fruit in fruits は「fruitsの各要素をfruitという変数で受け取って、繰り返し処理する」という意味なんだ。

happyの表情
初心者

わかりやすい!fruitって変数は自分で決められるの?

専門家

そうだよ。ループ変数の名前は自由に決められるんだ。ただし、意味のある名前をつけた方がコードが読みやすくなるよ。

let numbers = [1, 2, 3, 4, 5]

for number in numbers {
    print(number)
}

// または
for n in numbers {
    print(n)
}

単数形と複数形で対応させる(fruitsとfruit、numbersとnumber)のが一般的なスタイルなんだ。

配列のループ処理

専門家

配列のfor-inループをもう少し詳しく見ていこう。

基本的なループ

専門家

配列のすべての要素に対して処理を実行できるんだ。

let prices = [100, 200, 300]
var total = 0

for price in prices {
    total += price
}

print("合計: \(total)円")  // 合計: 600円

これで、配列のすべての要素を合計できたんだ。

インデックス付きループ

confusedの表情
初心者

要素だけじゃなくて、何番目かも知りたいときはどうするの?

専門家

いい質問だね。enumerated() メソッドを使えば、インデックスと要素の両方を取得できるんだ。

let fruits = ["りんご", "バナナ", "オレンジ"]

for (index, fruit) in fruits.enumerated() {
    print("\(index)番目: \(fruit)")
}
// 0番目: りんご
// 1番目: バナナ
// 2番目: オレンジ

enumerated() は、(インデックス, 要素) というタプルを返すんだ。(index, fruit) で、両方を同時に受け取っているんだよ。

happyの表情
初心者

おお!これは便利!

条件付きループ

専門家

ループの中で条件分岐を使うこともできるんだ。

let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

for number in numbers {
    if number % 2 == 0 {
        print("\(number)は偶数")
    } else {
        print("\(number)は奇数")
    }
}

これで、偶数と奇数を判定しながらループできるんだよ。

辞書のループ処理

専門家

辞書のfor-inループも見てみよう。

キーと値の両方を取得

専門家

辞書をループすると、キーと値のタプルが取得できるんだ。

let scores = [
    "Math": 85,
    "English": 92,
    "Science": 78
]

for (subject, score) in scores {
    print("\(subject): \(score)点")
}
// Math: 85点
// English: 92点
// Science: 78点

(subject, score) で、キーと値を同時に受け取っているんだ。変数名は自由に決められるよ。

キーだけ、値だけを取得

専門家

キーだけ、または値だけが欲しい場合は、keysvalues プロパティを使うんだ。

let scores = [
    "Math": 85,
    "English": 92,
    "Science": 78
]

// キーだけ
print("科目一覧:")
for subject in scores.keys {
    print(subject)
}

// 値だけ
var total = 0
for score in scores.values {
    total += score
}
print("合計点: \(total)点")

セットのループ処理

専門家

セットのループも、配列と同じように書けるんだ。

let tags: Set<String> = ["Swift", "iOS", "Programming"]

for tag in tags {
    print("#\(tag)")
}
// #Swift
// #iOS
// #Programming
// (順序は不定)

ただし、セットは順序が保証されていないから、毎回違う順序で処理される可能性があるんだよ。

範囲のループ処理

normalの表情
初心者

コレクションじゃなくて、単純に「1から10まで繰り返す」みたいなこともできるの?

専門家

できるよ!範囲演算子 を使えば、数値の範囲でループできるんだ。

閉範囲演算子(...)

専門家

1...5 で「1から5まで(5を含む)」という範囲を表すんだ。

for i in 1...5 {
    print(i)
}
// 1
// 2
// 3
// 4
// 5

これで、1から5まで5回ループするんだよ。

半開範囲演算子(..<)

専門家

..< を使うと、終端を含まない範囲になるんだ。

for i in 0..<5 {
    print(i)
}
// 0
// 1
// 2
// 3
// 4

0..<5 は「0から4まで」という意味なんだ。配列のインデックスとして使いやすいんだよ。

let fruits = ["りんご", "バナナ", "オレンジ"]

for i in 0..<fruits.count {
    print("\(i): \(fruits[i])")
}
// 0: りんご
// 1: バナナ
// 2: オレンジ

ループ変数を使わない場合

confusedの表情
初心者

ループ変数が必要ない場合はどうするの?単純に10回繰り返したいだけとか。

専門家

その場合は、アンダースコア _ を使うんだ。

for _ in 1...3 {
    print("Hello")
}
// Hello
// Hello
// Hello

_ は「この値は使わない」という意味なんだよ。

stride で複雑なループ

専門家

stride 関数を使えば、もっと複雑なループができるんだ。

一定間隔で進む

for i in stride(from: 0, to: 10, by: 2) {
    print(i)
}
// 0
// 2
// 4
// 6
// 8

stride(from:to:by:) は、fromからtoまで(toを含まない)、byの間隔で進むんだ。

逆順にループ

for i in stride(from: 5, through: 1, by: -1) {
    print(i)
}
// 5
// 4
// 3
// 2
// 1

stride(from:through:by:) は、throughで指定した値を含むんだよ。

ループの制御

normalの表情
初心者

ループの途中で抜けたり、スキップしたりすることはできるの?

専門家

できるよ!breakcontinue という制御文があるんだ。これは次の章で詳しく学ぶけど、簡単に紹介するね。

break:ループを抜ける

専門家

break を使うと、ループを途中で終了できるんだ。

let numbers = [1, 2, 3, 4, 5]

for number in numbers {
    if number == 3 {
        break  // 3になったらループを抜ける
    }
    print(number)
}
// 1
// 2

3に到達した時点でループが終了するんだよ。

continue:次の繰り返しにスキップ

専門家

continue を使うと、その回の処理をスキップして次の繰り返しに進むんだ。

let numbers = [1, 2, 3, 4, 5]

for number in numbers {
    if number == 3 {
        continue  // 3の時はスキップ
    }
    print(number)
}
// 1
// 2
// 4
// 5

3の時だけ print がスキップされるんだよ。

ネストしたループ

confusedの表情
初心者

ループの中にループを入れることってできるの?

専門家

できるよ!これを ネストしたループ って言うんだ。

for i in 1...3 {
    for j in 1...3 {
        print("(\(i), \(j))")
    }
}
// (1, 1)
// (1, 2)
// (1, 3)
// (2, 1)
// (2, 2)
// (2, 3)
// (3, 1)
// (3, 2)
// (3, 3)

外側のループが1回回るごとに、内側のループが3回回るんだ。

九九の表を作る

専門家

ネストしたループの実践例として、九九の表を作ってみよう。

for i in 1...9 {
    for j in 1...9 {
        let result = i * j
        print("\(i) × \(j) = \(result)")
    }
    print("---")  // 区切り線
}

これで、1の段から9の段まで全部出力できるんだよ。

ループのパフォーマンス

専門家

ループを書くときの、パフォーマンスに関するポイントも知っておこう。

ループの外に出せる処理

専門家

ループの中で毎回同じ計算をするのは無駄なんだ。

// 悪い例
let numbers = [1, 2, 3, 4, 5]
for number in numbers {
    let multiplier = 10  // 毎回同じ値を計算している
    print(number * multiplier)
}

// 良い例
let numbers = [1, 2, 3, 4, 5]
let multiplier = 10  // ループの外に出す
for number in numbers {
    print(number * multiplier)
}

ループの外に出せる処理は、外に出した方が効率的なんだよ。

countの取得

専門家

配列の count もループの外で取得しておくと良いことがあるんだ。

let fruits = ["りんご", "バナナ", "オレンジ"]
let count = fruits.count  // 一度だけ取得

for i in 0..<count {
    print(fruits[i])
}

ただし、Swiftのコンパイラは賢いから、多くの場合は最適化してくれるんだけどね。

実践練習

専門家

じゃあ、練習問題をやってみよう。

問題1: 1から100までの数値で、3の倍数だけを出力するプログラムを書いてみて。

excitedの表情
初心者

やってみる!

for number in 1...100 {
    if number % 3 == 0 {
        print(number)
    }
}

できた!

専門家

完璧だね!剰余演算子を使って3の倍数を判定しているね。

問題2: 配列の要素とそのインデックスを使って、「0番目: りんご」という形式で出力してみて。

normalの表情
初心者
let fruits = ["りんご", "バナナ", "オレンジ"]

for (index, fruit) in fruits.enumerated() {
    print("\(index)番目: \(fruit)")
}

こう?

専門家

素晴らしい!enumerated() を使いこなせているね。

最後に、少し難しい問題をやってみよう。

問題3: 九九の表で、答えが偶数のものだけを出力してみて。

confusedの表情
初心者

えーと、ネストしたループで...

for i in 1...9 {
    for j in 1...9 {
        let result = i * j
        if result % 2 == 0 {
            print("\(i) × \(j) = \(result)")
        }
    }
}

こうかな?

専門家

完璧だよ!ネストしたループと条件分岐を組み合わせて、偶数の結果だけを出力できているね。素晴らしい!

まとめ

この記事では、for-inループによる反復処理について学びました。

for-inループの基本:

  • for 要素 in コレクション { 処理 }
  • 配列、辞書、セット、範囲など様々なものに使える

配列のループ:

  • 基本:for item in array
  • インデックス付き:for (index, item) in array.enumerated()

辞書のループ:

  • キーと値:for (key, value) in dictionary
  • キーのみ:for key in dictionary.keys
  • 値のみ:for value in dictionary.values

セットのループ:

  • for item in set(順序は不定)

範囲のループ:

  • 閉範囲:for i in 1...5(1から5まで)
  • 半開範囲:for i in 0..<5(0から4まで)
  • stride:stride(from:to:by:)stride(from:through:by:)

ループの制御:

  • break:ループを抜ける
  • continue:次の繰り返しにスキップ

ネストしたループ:

  • ループの中にループを書ける
  • 外側が1回回るごとに内側が全回転する

次回から第4章「プログラムの流れを操る」に入ります。記事13「もし〜なら」として、if文による条件分岐について学びましょう!

← ブログ一覧に戻る