for 循环

for 和范围

for in 结构可用于迭代 Iterator。创建迭代器的最简单方法之一是使用范围表示法 a..b。这将产生从 a(包含)到 b(不包含)的值,步长为 1。

让我们使用 for 而不是 while 来编写 FizzBuzz。

fn main() {
    // `n` will take the values: 1, 2, ..., 100 in each iteration
    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` will take the values: 1, 2, ..., 100 in each iteration
    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 交互。如Iterator trait 部分所述,默认情况下,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 ^ Try deleting the & and matching just "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 ^ Comment out this line
}
  • 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 分支的类型,这是迭代类型的主要区别。类型的差异当然意味着可以执行不同的操作。

另请参阅

迭代器