Rustのfor
for は、範囲やコレクションを1つずつ順番にたどっていくループです。Rustの3種類のループの中で、いちばんよく使うことになるのがこの for です。
範囲をループする
Section titled “範囲をループする”fn main() { for i in 1..=5 { println!("{i}"); }}実行結果:
123451..=5 は両端を含む範囲(range)で、1から5までを表します。= を取って 1..5 にすると1つ手前で止まり、1から4までになります。この「1つずれる」間違いはうっかりやりがちなので、どちらのつもりで書いたのか確認するくせをつけましょう。
コレクションをループする
Section titled “コレクションをループする”for が本領を発揮するのはここです。インデックスを自分で管理しなくても、配列やベクタを順にたどれます。
fn main() { let fruits = ["りんご", "バナナ", "さくらんぼ"];
for fruit in fruits { println!("{fruit}"); }}実行結果:
りんごバナナさくらんぼwhile ループで自分で数を数えてインデックス(fruits[i])でアクセスする書き方と比べてみてください。こちらのほうが短く、インデックスを間違える心配もありません。配列とベクタについては、配列とベクタのページで詳しく学びます。
.enumerate()でインデックスも受け取る
Section titled “.enumerate()でインデックスも受け取る”位置と値の両方が必要なら、.enumerate() を使います。
fn main() { let fruits = ["りんご", "バナナ", "さくらんぼ"];
for (index, fruit) in fruits.iter().enumerate() { println!("{index}: {fruit}"); }}実行結果:
0: りんご1: バナナ2: さくらんぼ(index, fruit) の部分はタプルのパターンです。1回まわるごとにペアが渡され、ループがそれを2つの変数に分けてくれます。
逆順に数える・飛ばしながら数える
Section titled “逆順に数える・飛ばしながら数える”3からカウントダウンしたいときや、1つおきの数だけを扱いたいときはどうすればよいでしょう?最初に思いつくのは、3..=1 のような逆向きの範囲かもしれません。これはコンパイルできますが、ループは一度も実行されません。範囲は上向きにしか数えないので、始まりが終わりより大きい範囲は、ただの空っぽの範囲になるのです。
代わりに、ふつうの範囲を用意して、そのたどり方を変えます。
.rev()は範囲を逆順にたどります。.step_by(n)は最初の値から始めて、n個ごとに値を取り出します。
fn main() { for i in (1..=3).rev() { println!("{i}..."); } println!("スタート!");
for even in (0..=10).step_by(2) { print!("{even} "); } println!();
for i in 3..=1 { println!("これは表示されない: {i}"); }}実行結果:
3...2...1...スタート!0 2 4 6 8 10(1..=3).rev() のカッコに注目してください。カッコがないと、Rustは 1..=3.rev() を「1から 3.rev() まで」と読んでしまい、意図とは違うものになります。2つを組み合わせることもできます。(0..=10).rev().step_by(5) なら10、5、0になります。
数を数えるならwhileよりforがよい理由
Section titled “数を数えるならwhileよりforがよい理由”数を数えるループは while でも書けます。でも範囲を使った for なら、よくある間違いをまるごと防げます。カウンタを更新し忘れることもなければ、配列の終わりを1つ越えてしまう心配もありません。Rustのプログラマーは基本的に for を使い、ループの対象になる自然な範囲やコレクションがないときだけ while を使います。
1. 九九の7の段
Section titled “1. 九九の7の段”7 x 1 = 7 から 7 x 10 = 70 まで、7の段を表示してください。ヒント:1..=10 に対する for ループが1つあれば十分です。掛け算は println! の中で直接できます。
解答を見る
fn main() { for i in 1..=10 { println!("7 x {i} = {}", 7 * i); }}実行結果:
7 x 1 = 77 x 2 = 147 x 3 = 217 x 4 = 287 x 5 = 357 x 6 = 427 x 7 = 497 x 8 = 567 x 9 = 637 x 10 = 70{i} のような変数名は、波カッコの中に直接書けます。でも 7 * i のような計算は書けないので、空の {} を使い、カンマの後ろに値を渡しています。
2. 奇数を足し合わせる
Section titled “2. 奇数を足し合わせる”1から99までの奇数をすべて足して、合計を表示してください。ヒント:(1..100).step_by(2) で1、3、5、…、99が得られます。ループの外に mut の合計を用意しましょう。
解答を見る
fn main() { let mut total = 0;
for n in (1..100).step_by(2) { total += n; }
println!("1から99までの奇数の合計は{total}です");}実行結果:
1から99までの奇数の合計は2500です別の方法として、1..100 をループして、n % 2 == 1 のときだけ n を足すこともできます。どちらでも正解です。step_by は、1つずつチェックする代わりに偶数を飛ばしているだけです。
for 要素 in 範囲やコレクション { ... }は、Rustでふだん使いのループです。1..=5は両端を含み、1..5は5の1つ手前で止まります。- 配列やベクタを直接ループすれば、インデックスを使わずに各値を受け取れます。
- 値と一緒にインデックスも必要なときは
.enumerate()を使います。 3..=1のような逆向きの範囲は空です。カウントダウンには(1..=3).rev()を、飛ばしながら進むには.step_by(n)を使います。
理解度チェック
Section titled “理解度チェック”理解度チェック
1. forループで使う 1..=5 と 1..5 の違いは何ですか?
2. コレクションをループしながら、インデックスと値の両方を受け取るにはどうしますか?
3. コレクションを順に数えていくとき、ふつう while より for が好まれるのはなぜですか?
4. for i in 5..=1 { ... } はどうなりますか?
スコア: 0 / 4
さらに詳しく
Section titled “さらに詳しく”- forでコレクションを覗き見る — The Rust Programming Language 日本語版:
.rev()を使ったカウントダウンも含む、公式の入門です。 - for と range — Rust By Example 日本語版:範囲の実行できるサンプルに加えて、コレクションに使う
iter、iter_mut、into_iterも紹介しています。 - Iterator loops — The Rust Reference(英語):
forループが裏側で何をしているかの正確なルールです。 Iterator::step_by— 標準ライブラリのドキュメント(英語):step_byの動きを例付きで説明しています。revも同じページに載っています。