迭代器
学习目标
- 理解
Iterator trait
- 掌握
iter、into_iter、iter_mut 的区别
- 掌握常用适配器和消费者
- 理解惰性求值
核心概念
Iterator trait
trait Iterator {
type Item;
fn next(&mut self) -> Option<Self::Item>;
}
三种迭代方式
fn main() {
let v = vec![1, 2, 3];
for val in v.iter() {
println!("{}", val);
}
println!("v 仍可用: {:?}", v);
for val in v.into_iter() {
println!("{}", val);
}
let mut v = vec![1, 2, 3];
for val in v.iter_mut() {
*val *= 2;
}
println!("{:?}", v);
}
适配器(惰性)
fn main() {
let v = vec![1, 2, 3, 4, 5];
let doubled: Vec<i32> = v.iter().map(|x| x * 2).collect();
let evens: Vec<&i32> = v.iter().filter(|&&x| x % 2 == 0).collect();
for (i, val) in v.iter().enumerate() {
println!("[{}] = {}", i, val);
}
let names = vec!["Alice", "Bob"];
let ages = vec![25, 30];
let people: Vec<_> = names.iter().zip(ages.iter()).collect();
let a = vec![1, 2];
let b = vec![3, 4];
let combined: Vec<_> = a.iter().chain(b.iter()).collect();
let first_three: Vec<_> = v.iter().take(3).collect();
let skip_two: Vec<_> = v.iter().skip(2).collect();
}
消费者
fn main() {
let v = vec![1, 2, 3, 4, 5];
let doubled: Vec<i32> = v.iter().map(|x| x * 2).collect();
let sum: i32 = v.iter().sum();
let product: i32 = v.iter().product();
let count = v.iter().count();
let max = v.iter().max();
let min = v.iter().min();
let has_even = v.iter().any(|&x| x % 2 == 0);
let all_positive = v.iter().all(|&x| x > 0);
let first_even = v.iter().find(|&&x| x % 2 == 0);
let pos = v.iter().position(|&x| x == 3);
let sum = v.iter().fold(0, |acc, x| acc + x);
v.iter().for_each(|x| print!("{} ", x));
}
自定义迭代器
struct Counter {
count: u32,
max: u32,
}
impl Counter {
fn new(max: u32) -> Self {
Counter { count: 0, max }
}
}
impl Iterator for Counter {
type Item = u32;
fn next(&mut self) -> Option<Self::Item> {
if self.count < self.max {
self.count += 1;
Some(self.count)
} else {
None
}
}
}
fn main() {
let counter = Counter::new(5);
let values: Vec<u32> = counter.collect();
println!("{:?}", values);
let sum: u32 = Counter::new(5).sum();
println!("sum = {}", sum);
let evens: Vec<u32> = Counter::new(10).filter(|x| x % 2 == 0).collect();
println!("evens = {:?}", evens);
}
实践练习
练习 1:单词计数
fn word_count(text: &str) -> std::collections::HashMap<String, usize> {
text.split_whitespace()
.map(|w| w.to_lowercase())
.fold(std::collections::HashMap::new(), |mut map, word| {
*map.entry(word).or_insert(0) += 1;
map
})
}
fn main() {
let text = "hello world hello rust hello world";
let counts = word_count(text);
let mut sorted: Vec<_> = counts.iter().collect();
sorted.sort_by(|a, b| b.1.cmp(a.1));
for (word, count) in sorted {
println!("{}: {}", word, count);
}
}
练习 2:矩阵展平
fn flatten(matrix: &Vec<Vec<i32>>) -> Vec<i32> {
matrix.iter().flat_map(|row| row.iter().copied()).collect()
}
fn main() {
let matrix = vec![
vec![1, 2, 3],
vec![4, 5, 6],
vec![7, 8, 9],
];
let flat = flatten(&matrix);
println!("{:?}", flat);
}
练习 3:斐波那契
struct Fibonacci {
a: u64,
b: u64,
}
impl Fibonacci {
fn new() -> Self {
Fibonacci { a: 0, b: 1 }
}
}
impl Iterator for Fibonacci {
type Item = u64;
fn next(&mut self) -> Option<Self::Item> {
let result = self.a;
let new_b = self.a + self.b;
self.a = self.b;
self.b = new_b;
Some(result)
}
}
fn main() {
let fibs: Vec<u64> = Fibonacci::new().take(10).collect();
println!("{:?}", fibs);
}
常见错误
1. 忘记 collect
let v = vec![1, 2, 3];
let mapped = v.iter().map(|x| x * 2);
let mapped: Vec<_> = v.iter().map(|x| x * 2).collect();
2. 迭代器已消耗
let v = vec![1, 2, 3];
let iter = v.iter();
let sum: i32 = iter.sum();
小结
| 方法 | 类型 | 说明 |
|---|
iter() | 适配器 | 不可变借用 |
into_iter() | 适配器 | 获取所有权 |
iter_mut() | 适配器 | 可变借用 |
map, filter | 适配器 | 惰性转换 |
collect, sum | 消费者 | 触发计算 |
take, skip | 适配器 | 限制数量 |
zip, chain | 适配器 | 组合迭代器 |
fold | 消费者 | 累积计算 |