迭代器实战总结
> 综合运用迭代器知识,通过实战示例巩固数据处理的核心技能。
完整示例
示例 1:数据处理管道
rust
▶ Runfn main() {
let text = "Rust is a systems programming language that is blazingly fast";
// 统计词频
use std::collections::HashMap;
let word_count: 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
});
println!("词频统计:");
for (word, count) in &word_count {
println!(" {}: {}", word, count);
}
// 找出最长的 3 个单词
println!("\n最长的 3 个单词:");
let longest_three: Vec<_> = text
.split_whitespace()
.collect::<Vec<_>>()
.into_iter()
.fold(Vec::new(), |mut top, word| {
top.push(word);
top.sort_by(|a, b| b.len().cmp(&a.len()));
if top.len() > 3 {
top.pop();
}
top
});
for word in longest_three {
println!(" {} ({} 字符)", word, word.len());
}
}示例 2:用户过滤系统
rust
▶ Run#[derive(Debug, Clone)]
struct User {
id: u32,
name: String,
age: u32,
active: bool,
}
fn main() {
let users = vec![
User { id: 1, name: String::from("Alice"), age: 25, active: true },
User { id: 2, name: String::from("Bob"), age: 30, active: false },
User { id: 3, name: String::from("Charlie"), age: 35, active: true },
User { id: 4, name: String::from("David"), age: 20, active: true },
User { id: 5, name: String::from("Eve"), age: 28, active: false },
];
// 查询活跃用户
let active_users: Vec<&User> = users
.iter()
.filter(|u| u.active)
.collect();
println!("活跃用户:");
for user in active_users {
println!(" {} ({}岁)", user.name, user.age);
}
// 统计年龄段
println!("\n年龄段统计:");
let under_30 = users.iter().filter(|u| u.age < 30).count();
let between_30_and_35 = users.iter().filter(|u| u.age >= 30 && u.age <= 35).count();
let over_35 = users.iter().filter(|u| u.age > 35).count();
println!(" 30 岁以下:{}", under_30);
println!(" 30-35 岁:{}", between_30_and_35);
println!(" 35 岁以上:{}", over_35);
// 获取用户名字列表
let names: Vec<&String> = users.iter().map(|u| &u.name).collect();
println!("\n所有用户名:{:?}", names);
// 按年龄排序
let mut sorted_by_age = users.clone();
sorted_by_age.sort_by_key(|u| u.age);
println!("\n按年龄排序:");
for user in sorted_by_age {
println!(" {}: {} 岁", user.name, user.age);
}
}示例 3:解析器
rust
▶ Run/// 解析 CSV 格式的数据
fn parse_csv(input: &str) -> Vec<Vec<String>> {
input
.lines()
.map(|line| {
line.split(',')
.map(|field| field.trim().to_string())
.collect()
})
.collect()
}
fn main() {
let csv = "name,age,city
Alice,25,Beijing
Bob,30,Shanghai
Charlie,35,Guangzhou";
let data = parse_csv(csv);
println!("解析结果:");
for (i, row) in data.iter().enumerate() {
if i == 0 {
println!("表头:{:?}", row);
} else {
println!("行 {}: {:?}", i, row);
}
}
// 提取特定列
let names: Vec<&String> = data.iter().skip(1).map(|row| &row[0]).collect();
println!("\n姓名列:{:?}", names);
// 计算平均年龄
let avg_age: f64 = data.iter()
.skip(1)
.filter_map(|row| row.get(1))
.filter_map(|age| age.parse::<f64>().ok())
.sum::<f64>() / data.len().saturating_sub(1) as f64;
println!("平均年龄:{:.1}", avg_age);
}常见错误
错误 1:忘记消费迭代器
rust
▶ Runfn main() {
let numbers = vec![1, 2, 3];
// ❌ 错误:没有消费迭代器
numbers.iter().map(|x| x * 2);
// 什么都没发生!
// ✅ 正确:使用 collect 或其他消费方法
let doubled: Vec<i32> = numbers
.iter()
.map(|x| x * 2)
.collect();
}错误 2:迭代器耗尽后继续使用
rust
▶ Runfn main() {
let numbers = vec![1, 2, 3];
let mut iter = numbers.iter();
// 消耗迭代器
let all: Vec<_> = iter.collect();
println!("全部:{:?}", all);
// 迭代器已耗尽
let next = iter.next();
println!("下一个:{:?}", next); // None
}错误 3:借用问题
rust
▶ Runfn main() {
let mut numbers = vec![1, 2, 3];
// ❌ 错误:同时存在可变和不可变借用
// let iter = numbers.iter();
// numbers.push(4); // 不能修改
// println!("{:?}", iter);
// ✅ 正确:先完成迭代操作
{
let iter = numbers.iter();
for n in iter {
println!("{}", n);
}
} // 迭代结束
numbers.push(4); // 现在可以修改了
}错误 4:类型推断问题
rust
▶ Runfn main() {
let numbers = vec![1, 2, 3];
// ❌ 错误:collect 需要知道目标类型
// let doubled = numbers.iter().map(|x| x * 2).collect();
// ✅ 正确:添加类型标注
let doubled: Vec<i32> = numbers.iter().map(|x| x * 2).collect();
// 或者使用 turbofish
let doubled = numbers.iter().map(|x| x * 2).collect::<Vec<_>>();
}练习
练习 1:偶数平方和
计算 1 到 100 之间所有偶数的平方和:
rust
▶ Runlet sum: i32 = (1..=100)
// 实现练习 2:自定义 Range 迭代器
创建一个迭代器,生成等差数列:
rust
▶ Runstruct StepRange {
current: i32,
end: i32,
step: i32,
}练习 3:最长单词
找出字符串中最长的单词:
rust
▶ Runfn longest_word(text: &str) -> Option<&str> {
// 实现
}小结
迭代器方法分类
| 类别 | 方法 |
|---|---|
| 消费 | sum, count, collect, fold, for_each |
| 过滤 | filter, filter_map, take, skip, take_while, skip_while |
| 转换 | map, enumerate, zip, chain |
| 查询 | find, find_map, position, rposition |
| 统计 | max, min, max_by, min_by_key |
| 检查 | all, any |
关键要点
- 迭代器是惰性的:只有在消费时才执行
- next() 是唯一必需方法:其他都是适配器
- 零成本抽象:与手写循环性能相同
- 链式组合:多个操作可以高效组合
- 三种创建方式:
iter(),iter_mut(),into_iter()
小结
本章我们学习了:
- 迭代器的基本概念和惰性求值
- 消费适配器:sum、collect、fold
- 迭代器适配器:map、filter、enumerate
- 自定义迭代器的实现方法
- 实战案例:数据处理管道和用户过滤系统
练习题
详见:练习题