Rust のループと範囲

Beginner

This tutorial is from open-source community. Access the source code

はじめに

この実験では、Rust で for ループと範囲を使用する方法を学びます。for ループを a..b という範囲表記とともに使用することで、値の範囲を反復処理できます。たとえば、while ループの代わりに for ループを使って FizzBuzz プログラムを書くことができます。また、両端を含む範囲には ..= 表記を使用できます。for ループは、コレクションの各要素を借用する iter、コレクションを消費する into_iter、またはコレクションの各要素を可変的に借用する iter_mut など、さまざまな方法で反復子と相互作用することもできます。これらの各メソッドは、コレクション内のデータの異なるビューを提供し、さまざまなアクションを実行できるようにします。

注: 実験でファイル名が指定されていない場合は、好きなファイル名を使用できます。たとえば、main.rs を使用して、rustc main.rs &&./main でコンパイルして実行することができます。

for ループ

for と範囲

for in 構文を使って Iterator を反復処理できます。反復子を作成する最も簡単な方法の 1 つは、範囲表記 a..b を使うことです。これは、1 つずつのステップで a(含む)から b(含まない)までの値を生成します。

while の代わりに for を使って FizzBuzz を書いてみましょう。

fn main() {
    // `n` は各反復で 1、2、...、100 の値をとります
    for n in 1..101 {
        if n % 15 == 0 {
            println!("fizzbuzz");
        } else if n % 3 == 0 {
            println!("fizz");
        } else if n % 5 == 0 {
            println!("buzz");
        } else {
            println!("{}", n);
        }
    }
}

あるいは、両端を含む範囲には a..=b を使うことができます。上記のコードは次のように書けます。

fn main() {
    // `n` は各反復で 1、2、...、100 の値をとります
    for n in 1..=100 {
        if n % 15 == 0 {
            println!("fizzbuzz");
        } else if n % 3 == 0 {
            println!("fizz");
        } else if n % 5 == 0 {
            println!("buzz");
        } else {
            println!("{}", n);
        }
    }
}

for と反復子

for in 構文は、いくつかの方法で Iterator と相互作用することができます。反復子トレイトのセクションで説明したように、デフォルトでは for ループは into_iter 関数をコレクションに適用します。ただし、これがコレクションを反復子に変換する唯一の方法ではありません。

into_iteriteriter_mut はすべて、コレクション内のデータに対する異なるビューを提供することで、コレクションを反復子に変換する方法を異なる形で扱います。

  • iter - これは各反復でコレクションの各要素を借用します。したがって、コレクションはそのままで、ループの後も再利用可能です。
fn main() {
    let names = vec!["Bob", "Frank", "Ferris"];

    for name in names.iter() {
        match name {
            &"Ferris" => println!("There is a rustacean among us!"),
            // TODO ^ & を削除して、ただ "Ferris" と照合するようにしてみてください
            _ => println!("Hello {}", name),
        }
    }

    println!("names: {:?}", names);
}
  • into_iter - これはコレクションを消費するため、各反復で正確なデータが提供されます。コレクションが消費されると、それは 'ループ内で移動' されたため、再利用できなくなります。
fn main() {
    let names = vec!["Bob", "Frank", "Ferris"];

    for name in names.into_iter() {
        match name {
            "Ferris" => println!("There is a rustacean among us!"),
            _ => println!("Hello {}", name),
        }
    }

    println!("names: {:?}", names);
    // FIXME ^ この行をコメントアウトしてください
}
  • iter_mut - これはコレクションの各要素を可変的に借用し、コレクションをその場で変更できるようにします。
fn main() {
    let mut names = vec!["Bob", "Frank", "Ferris"];

    for name in names.iter_mut() {
        *name = match name {
            &mut "Ferris" => "There is a rustacean among us!",
            _ => "Hello",
        }
    }

    println!("names: {:?}", names);
}

上記のコードスニペットでは、match ブランチの型に注目してください。これが反復の型の主な違いです。型の違いは、もちろん実行できる異なるアクションを意味します。

まとめ

おめでとうございます!あなたは for ループの実験を完了しました。あなたの技術を向上させるために、LabEx でさらに実験を行って練習してください。