Skip to content

迭代器实战总结

> 综合运用迭代器知识,通过实战示例巩固数据处理的核心技能。

完整示例

示例 1:数据处理管道

rust
fn 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());
    }
}
▶ Run

示例 2:用户过滤系统

rust
#[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);
    }
}
▶ Run

示例 3:解析器

rust
/// 解析 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);
}
▶ Run

常见错误

错误 1:忘记消费迭代器

rust
fn 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();
}
▶ Run

错误 2:迭代器耗尽后继续使用

rust
fn 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
}
▶ Run

错误 3:借用问题

rust
fn 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);  // 现在可以修改了
}
▶ Run

错误 4:类型推断问题

rust
fn 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<_>>();
}
▶ Run

练习

练习 1:偶数平方和

计算 1 到 100 之间所有偶数的平方和:

rust
let sum: i32 = (1..=100)
    // 实现
▶ Run

练习 2:自定义 Range 迭代器

创建一个迭代器,生成等差数列:

rust
struct StepRange {
    current: i32,
    end: i32,
    step: i32,
}
▶ Run

练习 3:最长单词

找出字符串中最长的单词:

rust
fn longest_word(text: &str) -> Option<&str> {
    // 实现
}
▶ Run

小结

迭代器方法分类

类别方法
消费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

关键要点

  1. 迭代器是惰性的:只有在消费时才执行
  2. next() 是唯一必需方法:其他都是适配器
  3. 零成本抽象:与手写循环性能相同
  4. 链式组合:多个操作可以高效组合
  5. 三种创建方式iter(), iter_mut(), into_iter()

小结

本章我们学习了:

  • 迭代器的基本概念和惰性求值
  • 消费适配器:sum、collect、fold
  • 迭代器适配器:map、filter、enumerate
  • 自定义迭代器的实现方法
  • 实战案例:数据处理管道和用户过滤系统

练习题

详见:练习题