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_iter
、iter
和 iter_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
分支的类型,这是迭代类型的主要区别。类型的差异当然意味着可以执行不同的操作。