Rust 迭代器与闭包实战:用 filter/map/fold 替代手写循环

test12026-09-263 次阅读

迭代器的惰性求值

Rust 的迭代器是惰性的:iter()、filter、map 这类适配器只是描述计算过程,不立即执行,直到遇到 collect、sum、fold 等消费型方法才真正跑数据。这让你可以把多个变换串成一条流水线,且零额外分配。

常用适配器

let nums = vec![1, 2, 3, 4, 5, 6];

let even_sum: i32 = nums
    .iter()
    .filter(|&&x| x % 2 == 0)   // 保留偶数
    .map(|&x| x * x)            // 平方
    .sum();                     // 消费:1+4+16+36 = 57

println!("{}", even_sum);

相比手写 for 循环,链式写法没有中间数组,filter 和 map 通常还能被编译器内联到接近手写性能。

用 fold 实现自定义聚合

let words = ["a", "bb", "ccc"];
let total_len = words.iter().fold(0, |acc, w| acc + w.len());
// 等价于从 0 开始,对每个元素累加长度

fold 的初值类型不要求和元素类型相同,因此可以做"边走边构造一个 HashMap"这类转换,比 for 循环更声明式。

自定义迭代器

给自己的类型实现 Iterator trait,就能直接用 for 遍历或接上所有适配器。

struct Counter { n: u32, max: u32 }

impl Iterator for Counter {
    type Item = u32;
    fn next(&mut self) -> Option<u32> {
        self.n += 1;
        if self.n <= self.max { Some(self.n) } else { None }
    }
}

for i in Counter { n: 0, max: 3 } {
    println!("{}", i); // 1 2 3
}

闭包作为参数的三种 trait

把闭包传给函数时,按捕获方式选择 Fn、FnMut、FnOnce,决定能否多次调用或是否拿走所有权。

fn repeat(mut f: F, times: usize) {
    for _ in 0..times { f(); }
}

let mut count = 0;
repeat(|| { count += 1; }, 5);
println!("{}", count); // 5
  • 只读捕获用 Fn,要修改外部状态用 FnMut,要消费掉捕获值用 FnOnce。
  • 优先用迭代器而非索引循环,既安全又易于并行化(par_iter)。
T

test1

文章作者

迭代器的惰性求值 Rust 的迭代器是惰性的:iter()、filter、map 这类适配器只是描述计算过程,不立即执...

分类
技术
发布时间
2026-09-26
字数
约 1271 字
阅读
3 次