迭代器
约 1342 字大约 4 分钟
2025-09-26
在 Rust 中,迭代器是一类实现了 Iterator trait 的类型,迭代器模式允许对一个序列中的项执行某些操作
重要
迭代器是惰性的。在调用消费迭代器的方法之前,其不会执行任何操作
fn main() {
let v1 = vec![1, 2, 3];
let v1_iter = v1.iter();
}上述代码中,迭代器被存储在 v1_iter 变量中。一旦迭代器创建后,就可以选择用多种方式使用它
注
iter()产出不可变引用iter_mut()产出可变引用into_iter()取得所有权,产出拥有所有权的值
Iterator trait 和 next 方法
每个迭代器都实现了名为 Iterator 的 trait,其中 next 是唯一必须实现的方法,每次调用要么返回 Some(下一个元素),要么返回 None 表示结束
pub trait Iterator {
// type Item 与 Self::Item 是关联类型,要求实现者定义产出的元素类型
type Item;
fn next(&mut self) -> Option<Self::Item>;
// ...
}使用 for 循环会默认调用 IntoIterator 生成迭代器,然后再反复调用 next
for 循环
fn main() {
let v1 = vec![1, 2, 3];
let v1_iter = v1.iter();
for item in v1_iter {
println!("Got: {item}");
}
}消费适配器
消费适配器指的是在 Iterator 默认提供的方法中在其内部定义的过程中使用了 next 的方法
常见的消费适配器
- 查找:
find、find_map - 位置:
last()、nth(n) - 布尔判断:
all()、any() - 转换为集合类型:
collect() - 取极值:
max/min()、max_by/min_by() - 聚合/累计:
sum()、product()、count()、fold()、reduce()
聚合/累计
fn main() {
let nums = [1, 2, 3];
let sum: i32 = nums.iter().sum(); // 累加
let product: i32 = nums.iter().product(); // 累乘
let cnt = nums.iter().count(); // 统计长度
println!("{sum}, {product}, {cnt}");
}收集为集合
use std::collections::HashMap;
fn main() {
let pairs = [("a", 1), ("b", 2)];
// 收集到 Vec
let vec: Vec<_> = pairs.iter().collect();
// 收集到 HashMap
let map: HashMap<_, _> = pairs.into_iter().collect();
println!("{:?} {:?}", vec, map);
}位置与末尾
fn main() {
let mut it = [10, 20, 30].iter();
assert_eq!(it.nth(1), Some(&20));
assert_eq!(it.last(), Some(&30));
}查找与布尔短路
fn main() {
let words = ["foo", "bar", "baz"];
// find: 闭包函数返回一个 bool
// find_map: 闭包函数返回 Option
let hit = words.iter().find(|w| w.starts_with('b'));
let len = words.iter().find_map(|w| w.len().checked_sub(10));
// any 至少有一个满足
// all 所有元素都要满足
// 都返回 bool
let any_b = words.iter().any(|w| w.starts_with('b'));
let all_short = words.iter().all(|w| w.len() <= 3);
println!("{hit:?} {len:?} {any_b} {all_short}");
}自定义累计
fn main() {
// fold 从一个初始值开始累积,永远有返回值
// reduce 用第一个元素当初始值,可能没有返回值
// 都返回上一次的累计值
let sum = [1, 2, 3].iter().fold(0, |acc, x| acc + x);
let concat = ["a", "b", "c"].iter().cloned().reduce(|a, b| a + b);
println!("{sum} {concat:?}");
}极值
fn main() {
let vals = [("a", 3), ("b", 1), ("c", 2)];
let max = vals.iter().max_by_key(|(_, v)| *v);
let min = vals.iter().min();
println!("{max:?} {min:?}");
}迭代器适配器
迭代器适配器不会直接消耗迭代器,而是基于现有迭代器返回新的迭代器(惰性)。只有搭配消费适配器或手动 next 才会真正执行
常见的迭代器适配器
- 重排/循环:
rev、cycle - 展开/压平:
flat_map、flatten - 去重(针对 slice):
dedup、dedup_by - 转换/过滤:
map、filter、filter_map - 组合/辅助:
zip、enumerate、inspect、peekable、fuse - 链接/截断:
chain、take、skip、take_while、skip_while - 窗口/分组:
chunks、array_chunks、windows(在 slice 上)、map_while、scan
map 惰性
fn main() {
let v1 = vec![1, 2, 3];
// 仅创建迭代器,未消费,什么都不发生
// 编译会警告:unused Map,iterators are lazy
v1.iter().map(|x| x + 1);
// 使用 collect 触发消费
let v2: Vec<_> = v1.iter().map(|x| x + 1).collect();
assert_eq!(v2, vec![2, 3, 4]);
}过滤
fn main() {
let words = ["foo", "bar1", "baz"];
let only_digit_tail: Vec<_> = words
.iter()
.filter(|w| w.chars().any(char::is_numeric))
.collect();
let parsed: Vec<_> = ["1", "x", "3"]
.iter()
.filter_map(|s| s.parse::<i32>().ok())
.collect();
assert_eq!(only_digit_tail, vec![&"bar1"]);
assert_eq!(parsed, vec![1, 3]);
}链接/截断
fn main() {
let a = [1, 2];
let b = [3, 4];
// chain: 拼接两个迭代器
// take: 只取前 N 个
// skip: 跳过前 N 个
let chained: Vec<_> = a.iter().chain(b.iter()).cloned().collect();
let first_two: Vec<_> = (0..10).take(2).collect();
let skip_one: Vec<_> = (0..5).skip(1).collect();
assert_eq!(chained, vec![1, 2, 3, 4]);
assert_eq!(first_two, vec![0, 1]);
assert_eq!(skip_one, vec![1, 2, 3, 4]);
}组合
fn main() {
let names = ["a", "b", "c"];
let scores = [10, 20, 30];
// zip: 配对两个迭代器的元素成为一个元组
// enumerate:
// 会在元素前面加上从 0 开始的索引,把迭代器的每项变成 (index, item) 的元组
let pairs: Vec<_> = names.iter().zip(scores.iter()).collect();
let indexed: Vec<_> = names.iter().enumerate().collect();
println!("{pairs:?} {indexed:?}");
}展开/压平
fn main() {
let nested = vec![vec![1, 2], vec![3]];
// flatten: 把迭代器扁平化
// flat_map: 返回子迭代器,再压平
let flat: Vec<_> = nested.iter().flatten().cloned().collect();
let doubled: Vec<_> = [1, 2, 3]
.iter()
.flat_map(|x| [x, x])
.copied()
.collect();
assert_eq!(flat, vec![1, 2, 3]);
assert_eq!(doubled, vec![1, 1, 2, 2, 3, 3]);
}重排/循环
fn main() {
// rev: 反转迭代顺序
// cycle: 无限循环
let rev: Vec<_> = (1..=3).rev().collect();
let mut cycled = (1..=2).cycle();
assert_eq!(cycled.next(), Some(1));
assert_eq!(cycled.next(), Some(2));
assert_eq!(cycled.next(), Some(1));
}注
适配器可任意链式组合,但必须以消费步骤结尾(如 collect/sum/for)才能执行闭包逻辑