Rust —— 迭代器

迭代器(Iterator)是 Rust 中用于处理元素序列的强大工具。迭代器模式允许你对一系列项进行某些操作,而无需手动管理索引或循环逻辑。Rust 的迭代器是惰性的(lazy),只在需要时才会执行计算,这使得它们既高效又灵活。

1. 迭代器基础

1.1 创建迭代器

在 Rust 中,所有集合类型都可以创建迭代器:

1
2
3
4
5
6
7
8
9
10
11
fn main() {
let v1 = vec![1, 2, 3];

// 创建迭代器(惰性的,此时不会执行任何操作)
let v1_iter = v1.iter();

// 使用 for 循环消费迭代器
for val in v1_iter {
println!("值: {}", val);
}
}

1.2 三种迭代方法

Rust 提供三种获取迭代器的方法,它们在所有权处理上有所不同:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
fn main() {
let v = vec![1, 2, 3];

// iter() - 返回不可变引用
for val in v.iter() {
println!("不可变引用: {}", val); // val 的类型是 &i32
}

// iter_mut() - 返回可变引用
let mut v_mut = vec![1, 2, 3];
for val in v_mut.iter_mut() {
*val += 1; // val 的类型是 &mut i32
}
println!("修改后: {:?}", v_mut);

// into_iter() - 获取所有权
for val in v.into_iter() {
println!("获取所有权: {}", val); // val 的类型是 i32
}
// println!("{:?}", v); // 错误!v 已被移动
}

2. Iterator Trait

2.1 Iterator trait 定义

所有迭代器都实现了 Iterator trait:

1
2
3
4
5
6
7
pub trait Iterator {
type Item;

fn next(&mut self) -> Option<Self::Item>;

// 还有许多提供默认实现的方法...
}

2.2 手动调用 next 方法

1
2
3
4
5
6
7
8
9
fn main() {
let v1 = vec![1, 2, 3];
let mut v1_iter = v1.iter();

assert_eq!(v1_iter.next(), Some(&1));
assert_eq!(v1_iter.next(), Some(&2));
assert_eq!(v1_iter.next(), Some(&3));
assert_eq!(v1_iter.next(), None);
}

注意:调用 next 需要 mut,因为迭代器内部状态会改变。

2.3 实现自定义迭代器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
struct Counter {
count: u32,
}

impl Counter {
fn new() -> Counter {
Counter { count: 0 }
}
}

impl Iterator for Counter {
type Item = u32;

fn next(&mut self) -> Option<Self::Item> {
if self.count < 5 {
self.count += 1;
Some(self.count)
} else {
None
}
}
}

fn main() {
let mut counter = Counter::new();

assert_eq!(counter.next(), Some(1));
assert_eq!(counter.next(), Some(2));
assert_eq!(counter.next(), Some(3));
assert_eq!(counter.next(), Some(4));
assert_eq!(counter.next(), Some(5));
assert_eq!(counter.next(), None);
}

3. 消费适配器(Consuming Adaptors)

消费适配器会调用 next 方法,消耗迭代器:

3.1 sum - 求和

1
2
3
4
5
6
7
8
9
fn main() {
let v1 = vec![1, 2, 3];
let v1_iter = v1.iter();

let total: i32 = v1_iter.sum();

println!("总和: {}", total); // 6
// println!("{:?}", v1_iter); // 错误!迭代器已被消费
}

3.2 collect - 收集为集合

1
2
3
4
5
6
7
fn main() {
let v1: Vec<i32> = vec![1, 2, 3];

let v2: Vec<_> = v1.iter().collect();

println!("收集结果: {:?}", v2);
}

3.3 其他消费适配器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
fn main() {
let numbers = vec![1, 2, 3, 4, 5];

// count - 计数
let count = numbers.iter().count();
println!("元素数量: {}", count);

// last - 最后一个元素
let last = numbers.iter().last();
println!("最后元素: {:?}", last);

// max 和 min
let max = numbers.iter().max();
let min = numbers.iter().min();
println!("最大值: {:?}, 最小值: {:?}", max, min);
}

4. 迭代器适配器(Iterator Adaptors)

迭代器适配器会产生新的迭代器,它们是惰性的:

4.1 map - 映射转换

1
2
3
4
5
6
7
8
9
10
fn main() {
let v1: Vec<i32> = vec![1, 2, 3];

// map 是惰性的,不会立即执行
let v2: Vec<_> = v1.iter()
.map(|x| x + 1)
.collect();

println!("映射后: {:?}", v2); // [2, 3, 4]
}

4.2 filter - 过滤元素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#[derive(PartialEq, Debug)]
struct Shoe {
size: u32,
style: String,
}

fn shoes_in_size(shoes: Vec<Shoe>, shoe_size: u32) -> Vec<Shoe> {
shoes.into_iter()
.filter(|s| s.size == shoe_size)
.collect()
}

fn main() {
let shoes = vec![
Shoe { size: 10, style: String::from("运动鞋") },
Shoe { size: 13, style: String::from("凉鞋") },
Shoe { size: 10, style: String::from("靴子") },
];

let in_my_size = shoes_in_size(shoes, 10);

println!("我的尺码: {:?}", in_my_size);
}

4.3 常用迭代器适配器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
fn main() {
let numbers = vec![1, 2, 3, 4, 5];

// take - 获取前 n 个元素
let first_three: Vec<_> = numbers.iter()
.take(3)
.collect();
println!("前三个: {:?}", first_three);

// skip - 跳过前 n 个元素
let after_two: Vec<_> = numbers.iter()
.skip(2)
.collect();
println!("跳过两个: {:?}", after_two);

// enumerate - 添加索引
for (index, value) in numbers.iter().enumerate() {
println!("索引 {}: 值 {}", index, value);
}

// zip - 组合两个迭代器
let letters = vec!['a', 'b', 'c'];
let zipped: Vec<_> = numbers.iter().zip(letters.iter()).collect();
println!("组合结果: {:?}", zipped);
}

5. 链式调用

迭代器的强大之处在于可以链式调用多个方法:

5.1 复杂的数据处理

1
2
3
4
5
6
7
8
9
10
fn main() {
let numbers = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

let result: i32 = numbers.iter()
.filter(|&&x| x % 2 == 0) // 过滤偶数
.map(|&x| x * x) // 平方
.sum(); // 求和

println!("偶数平方和: {}", result); // 220
}

5.2 字符串处理

1
2
3
4
5
6
7
8
9
fn main() {
let text = "hello world rust programming";

let long_words: Vec<&str> = text.split_whitespace()
.filter(|word| word.len() > 5)
.collect();

println!("长单词: {:?}", long_words);
}

5.3 结构化数据处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#[derive(Debug)]
struct Person {
name: String,
age: u32,
}

fn main() {
let people = vec![
Person { name: String::from("Alice"), age: 30 },
Person { name: String::from("Bob"), age: 25 },
Person { name: String::from("Charlie"), age: 35 },
];

let names: Vec<String> = people.iter()
.filter(|p| p.age > 28)
.map(|p| p.name.clone())
.collect();

println!("年龄大于28的人: {:?}", names);
}

6. 实用方法

6.1 find - 查找元素

1
2
3
4
5
6
7
8
9
10
fn main() {
let numbers = vec![1, 2, 3, 4, 5];

let first_even = numbers.iter().find(|&&x| x % 2 == 0);

match first_even {
Some(&n) => println!("第一个偶数: {}", n),
None => println!("没有偶数"),
}
}

6.2 any 和 all - 条件检查

1
2
3
4
5
6
7
8
9
fn main() {
let numbers = vec![1, 2, 3, 4, 5];

let has_even = numbers.iter().any(|&x| x % 2 == 0);
println!("有偶数: {}", has_even);

let all_positive = numbers.iter().all(|&x| x > 0);
println!("全是正数: {}", all_positive);
}

6.3 fold - 累积计算

1
2
3
4
5
6
7
8
9
10
fn main() {
let numbers = vec![1, 2, 3, 4, 5];

// fold 的第一个参数是初始值,第二个是累积函数
let sum = numbers.iter().fold(0, |acc, &x| acc + x);
println!("总和: {}", sum);

let product = numbers.iter().fold(1, |acc, &x| acc * x);
println!("乘积: {}", product);
}

6.4 flat_map - 扁平化映射

1
2
3
4
5
6
7
8
9
fn main() {
let words = vec!["hello", "world"];

let chars: Vec<char> = words.iter()
.flat_map(|word| word.chars())
.collect();

println!("所有字符: {:?}", chars);
}

7. 迭代器与性能

7.1 零成本抽象

Rust 的迭代器是零成本抽象,编译后的性能与手写循环相当:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 使用迭代器
fn sum_iterator(numbers: &[i32]) -> i32 {
numbers.iter().sum()
}

// 使用循环
fn sum_loop(numbers: &[i32]) -> i32 {
let mut sum = 0;
for &n in numbers {
sum += n;
}
sum
}

// 两者编译后的性能几乎相同

7.2 惰性求值的优势

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
fn main() {
let numbers = vec![1, 2, 3, 4, 5];

// 这些操作不会立即执行
let iter = numbers.iter()
.map(|x| {
println!("映射 {}", x);
x * 2
})
.filter(|x| {
println!("过滤 {}", x);
x > &5
});

// 只有在需要结果时才会执行
println!("开始收集:");
let result: Vec<_> = iter.collect();
println!("结果: {:?}", result);
}

8. 高级用法

8.1 组合多个迭代器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
fn main() {
let counter = Counter::new();

let sum: u32 = counter
.zip(Counter::new().skip(1))
.map(|(a, b)| a * b)
.filter(|x| x % 3 == 0)
.sum();

println!("结果: {}", sum); // 18
}

struct Counter {
count: u32,
}

impl Counter {
fn new() -> Counter {
Counter { count: 0 }
}
}

impl Iterator for Counter {
type Item = u32;

fn next(&mut self) -> Option<Self::Item> {
if self.count < 5 {
self.count += 1;
Some(self.count)
} else {
None
}
}
}

8.2 范围迭代器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
fn main() {
// 范围也是迭代器
for i in 0..5 {
println!("{}", i);
}

// 反向迭代
for i in (0..5).rev() {
println!("{}", i);
}

// 步长迭代
for i in (0..10).step_by(2) {
println!("{}", i);
}
}

8.3 partition - 分区

1
2
3
4
5
6
7
8
9
fn main() {
let numbers = vec![1, 2, 3, 4, 5, 6];

let (evens, odds): (Vec<_>, Vec<_>) = numbers.into_iter()
.partition(|&x| x % 2 == 0);

println!("偶数: {:?}", evens);
println!("奇数: {:?}", odds);
}

9. 常见陷阱与最佳实践

9.1 避免不必要的 collect

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 不好的做法 - 创建了临时 Vec
fn sum_of_squares_bad(numbers: &[i32]) -> i32 {
let squares: Vec<_> = numbers.iter()
.map(|x| x * x)
.collect();
squares.iter().sum()
}

// 好的做法 - 直接链式调用
fn sum_of_squares_good(numbers: &[i32]) -> i32 {
numbers.iter()
.map(|x| x * x)
.sum()
}

fn main() {
let numbers = vec![1, 2, 3, 4, 5];
println!("平方和: {}", sum_of_squares_good(&numbers));
}

9.2 注意迭代器的消费

1
2
3
4
5
6
7
8
9
10
11
12
13
14
fn main() {
let v = vec![1, 2, 3];
let iter = v.iter();

// 错误示例:迭代器只能使用一次
// let sum: i32 = iter.sum();
// let count = iter.count(); // 错误!iter 已被消费

// 正确做法:重新创建迭代器
let sum: i32 = v.iter().sum();
let count = v.iter().count();

println!("总和: {}, 数量: {}", sum, count);
}

9.3 使用迭代器而非索引

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
fn main() {
let numbers = vec![1, 2, 3, 4, 5];

// 不推荐:使用索引
for i in 0..numbers.len() {
println!("{}", numbers[i]);
}

// 推荐:直接迭代
for num in &numbers {
println!("{}", num);
}

// 需要索引时使用 enumerate
for (index, num) in numbers.iter().enumerate() {
println!("索引 {}: {}", index, num);
}
}

10. 实战案例

10.1 统计单词频率

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
use std::collections::HashMap;

fn word_frequency(text: &str) -> HashMap<String, usize> {
text.split_whitespace()
.map(|word| word.to_lowercase())
.fold(HashMap::new(), |mut map, word| {
*map.entry(word).or_insert(0) += 1;
map
})
}

fn main() {
let text = "Hello world hello Rust world";
let freq = word_frequency(text);

for (word, count) in freq {
println!("{}: {}", word, count);
}
}

10.2 数据转换管道

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#[derive(Debug)]
struct Product {
name: String,
price: f64,
category: String,
}

fn main() {
let products = vec![
Product { name: "笔记本".to_string(), price: 5000.0, category: "电子".to_string() },
Product { name: "鼠标".to_string(), price: 100.0, category: "电子".to_string() },
Product { name: "书籍".to_string(), price: 50.0, category: "图书".to_string() },
Product { name: "键盘".to_string(), price: 300.0, category: "电子".to_string() },
];

// 找出电子类别中价格超过200的产品名称
let expensive_electronics: Vec<String> = products.iter()
.filter(|p| p.category == "电子")
.filter(|p| p.price > 200.0)
.map(|p| p.name.clone())
.collect();

println!("昂贵的电子产品: {:?}", expensive_electronics);
}

10.3 矩阵转置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
fn transpose(matrix: Vec<Vec<i32>>) -> Vec<Vec<i32>> {
if matrix.is_empty() {
return vec![];
}

let rows = matrix.len();
let cols = matrix[0].len();

(0..cols)
.map(|col| {
(0..rows)
.map(|row| matrix[row][col])
.collect()
})
.collect()
}

fn main() {
let matrix = vec![
vec![1, 2, 3],
vec![4, 5, 6],
];

let transposed = transpose(matrix);

for row in transposed {
println!("{:?}", row);
}
}

10.4 查找重复元素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
use std::collections::HashSet;

fn find_duplicates(numbers: &[i32]) -> Vec<i32> {
let mut seen = HashSet::new();
let mut duplicates = HashSet::new();

numbers.iter()
.filter(|&&num| !seen.insert(num))
.for_each(|&num| { duplicates.insert(num); });

duplicates.into_iter().collect()
}

fn main() {
let numbers = vec![1, 2, 3, 2, 4, 5, 1, 6];
let dups = find_duplicates(&numbers);

println!("重复的元素: {:?}", dups);
}

10.5 分组和聚合

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
use std::collections::HashMap;

#[derive(Debug)]
struct Sale {
product: String,
amount: f64,
}

fn group_by_product(sales: Vec<Sale>) -> HashMap<String, f64> {
sales.into_iter()
.fold(HashMap::new(), |mut map, sale| {
*map.entry(sale.product).or_insert(0.0) += sale.amount;
map
})
}

fn main() {
let sales = vec![
Sale { product: "苹果".to_string(), amount: 100.0 },
Sale { product: "香蕉".to_string(), amount: 50.0 },
Sale { product: "苹果".to_string(), amount: 150.0 },
Sale { product: "橙子".to_string(), amount: 80.0 },
Sale { product: "香蕉".to_string(), amount: 30.0 },
];

let totals = group_by_product(sales);

for (product, total) in totals {
println!("{}: {:.2}", product, total);
}
}

11. 迭代器与错误处理

11.1 filter_map - 过滤和映射

1
2
3
4
5
6
7
8
9
fn main() {
let strings = vec!["1", "2", "three", "4", "5"];

let numbers: Vec<i32> = strings.iter()
.filter_map(|s| s.parse().ok())
.collect();

println!("解析成功的数字: {:?}", numbers);
}

11.2 处理 Result 序列

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
fn main() {
let strings = vec!["1", "2", "three", "4"];

// 方法1: collect 到 Result
let result: Result<Vec<i32>, _> = strings.iter()
.map(|s| s.parse::<i32>())
.collect();

match result {
Ok(numbers) => println!("所有解析成功: {:?}", numbers),
Err(e) => println!("解析失败: {}", e),
}

// 方法2: 使用 filter_map 跳过错误
let numbers: Vec<i32> = strings.iter()
.filter_map(|s| s.parse().ok())
.collect();

println!("部分解析成功: {:?}", numbers);
}

12. 性能优化技巧

12.1 使用 drain 避免复制

1
2
3
4
5
6
7
8
9
fn main() {
let mut v = vec![1, 2, 3, 4, 5];

// drain 会移除并返回元素,避免复制
let first_three: Vec<_> = v.drain(0..3).collect();

println!("提取的: {:?}", first_three);
println!("剩余的: {:?}", v);
}

12.2 避免重复计算

1
2
3
4
5
6
7
8
9
10
11
12
13
fn main() {
let numbers = vec![1, 2, 3, 4, 5];

// 不好:重复调用 iter()
// let sum: i32 = numbers.iter().sum();
// let count = numbers.iter().count();

// 好:使用 fold 一次遍历
let (sum, count) = numbers.iter()
.fold((0, 0), |(sum, count), &x| (sum + x, count + 1));

println!("总和: {}, 数量: {}", sum, count);
}

12.3 使用 by_ref 保留迭代器

1
2
3
4
5
6
7
8
9
10
11
12
fn main() {
let mut iter = vec![1, 2, 3, 4, 5].into_iter();

// 使用 by_ref 只消费部分迭代器
let first_two: Vec<_> = iter.by_ref().take(2).collect();

println!("前两个: {:?}", first_two);

// 继续使用剩余的迭代器
let rest: Vec<_> = iter.collect();
println!("剩余的: {:?}", rest);
}

总结

迭代器是 Rust 中处理序列数据的核心工具,掌握它能让你的代码更加:

  • 简洁优雅:用链式调用替代复杂的循环逻辑
  • 安全可靠:编译期保证类型安全,避免越界访问
  • 高效性能:零成本抽象,编译后性能与手写循环相当
  • 函数式风格:结合闭包实现声明式编程
  • 可组合性:多个简单操作组合成复杂的数据处理管道

迭代器与闭包是 Rust 函数式编程的两大支柱,它们共同构成了 Rust 中优雅而高效的数据处理范式。熟练运用迭代器,是编写惯用 Rust 代码的必备技能。

Hooray!Iterators 小节完成!!!