文章目录
Rust迭代器
迭代器适用于对集合进行逐个遍历操作的对象
迭代器是通过iterator trait
来定义的,需要我们实现next
方法,用于返回迭代器的下一个元素,如果没有下一个元素应该返回None
表示结束
其他默认实现的方法有map
filter
等
rust
pub trait Iterator{
type Item;
fn next(&mut self) -> Option<Self::Item>;
}
迭代器有以下的一些特性
- 惰性求值:这个意思是迭代器本身不回立即进行任何计算或者操作,除非我们显示的要求获取数据,迭代器才会返回数据,这样就可以避免不必要的计算
- 所有权和借用检查:迭代器严格遵守所有权和借用的规则,具体是什么我们后面会讲到,这里我们只要知道,这是为了避免数据竞争和内存错误
- 链式调用:Rust迭代器支持链式调用
- 抽象和通用性:Rust迭代器通过
Iterator trail
实现抽象和通用性
迭代器的使用
创建迭代器
可以通过.iter()
.iter_mut
.into_iter()
来创建迭代器
第一个是不可变引用迭代器,第二个是可变引用迭代器,第三个是将集合的所有权转移,并生成值的迭代器,暂时可以理解为,用一次就会失效
例如
rust
let vec = vec![1, 2, 3];
let iter = vec.iter();
let iter_mut = vec.iter_mut();
let into_iter = vec.into_iter();
迭代器的方法
我们获取到迭代器的目的是为了获取数据或者遍历数据,这其实是通过迭代器的方法实现的
map()
:对集合里的每个元素按照传入的方法转换
collect()
: 这个方法是消耗迭代器用的,说人话就是用一个少一个,并且每一个都要用,最后返回一个结果,类似的还有sum()
求和 ,product()
求积,count()
求元素个数
rust
let vec = vec![1, 2, 3, 4, 5];
let squared_vec: Vec<i32> = vec.iter().map(|x| x * x).collect();
filter()
; 根据传入的方法过滤元素
rust
let vec = vec![1, 2, 3, 4, 5];
let filtered_vec: Vec<i32> = vec.into_iter().filter(|&x| x % 2 == 0).collect();
这里filter留下的条件为true的元素
其他方法
fold()
:对集合中的元素进行累积处理,可以自定义累积规则
skip()
: 跳过前n个元素
take()
: 取前n个元素
enumerate()
: 获取索引和值
find()
:查找满足条件的第一个元素
any()
:判断是否存在元素符合条件
all()
: 判断是否所有元素符合条件
for循环遍历迭代器
rust
let vec = vec![1, 2, 3, 4, 5];
for &num in vec.iter() {
println!("{} ", num);
}
惰性求值
现在我们对惰性求值会更好理解了,因为iterator会有一些方法,例如map,filter之类的,调用之后不会立刻执行操作,直到调用了类似于collect之类的方法才会真正处理数据
自定义迭代器
我们也可以为自己的类型实现迭代器 iterator trait(可以理解为接口)
只需要定义next方法即可,例如
rust
struct Counter {
count: usize,
}
impl Counter {
fn new() -> Counter {
Counter { count: 0 }
}
}
impl Iterator for Counter {
type Item = usize;
fn next(&mut self) -> Option<Self::Item> {
self.count += 1;
if self.count <= 5 {
Some(self.count)
} else {
None
}
}
}
let mut counter = Counter::new();
while let Some(num) = counter.next() {
println!("{}", num); // 输出 1 到 5
}
这里我们先不去管 impl 是什么,直接翻译的话是实例,适用于给结构体或者特性实现方法的一个关键字
Rust 迭代器方法
以下是一些 Rust 中常用的迭代器方法,以及它们的简要说明和示例:
方法名 | 描述 | 示例 |
---|---|---|
next() |
返回迭代器中的下一个元素。 | let mut iter = (1..5).into_iter(); while let Some(val) = iter.next() { println!("{}", val); } |
size_hint() |
返回迭代器中剩余元素数量的下界和上界。 | let iter = (1..10).into_iter(); println!("{:?}", iter.size_hint()); |
count() |
计算迭代器中的元素数量。 | let count = (1..10).into_iter().count(); |
nth() |
返回迭代器中第 n 个元素。 | let third = (0..10).into_iter().nth(2); |
last() |
返回迭代器中的最后一个元素。 | let last = (1..5).into_iter().last(); |
all() |
如果迭代器中的所有元素都满足某个条件,返回 true 。 |
`let all_positive = (1...=5).into_iter().all( |
any() |
如果迭代器中的至少一个元素满足某个条件,返回 true 。 |
`let any_negative = (1...5).into_iter().any( |
find() |
返回迭代器中第一个满足某个条件的元素。 | `let first_even = (1...10).into_iter().find( |
find_map() |
对迭代器中的元素应用一个函数,返回第一个返回 Some 的结果。 |
`let first_letter = "hello".chars().find_map( |
map() |
对迭代器中的每个元素应用一个函数。 | `let squares: Vec = (1...5).into_iter().map( |
filter() |
保留迭代器中满足某个条件的元素。 | `let evens: Vec = (1...10).into_iter().filter( |
filter_map() |
对迭代器中的元素应用一个函数,如果函数返回 Some ,则保留结果。 |
`let chars: Vec = "hello".chars().filter_map( |
map_while() |
对迭代器中的元素应用一个函数,直到函数返回 None 。 |
`let first_three = (1...).into_iter().map_while( |
take_while() |
从迭代器中取出满足某个条件的元素,直到不满足为止。 | `let first_five = (1...10).into_iter().take_while( |
skip_while() |
跳过迭代器中满足某个条件的元素,直到不满足为止。 | `let odds: Vec = (1...10).into_iter().skip_while( |
for_each() |
对迭代器中的每个元素执行某种操作。 | `let mut counter = 0; (1...5).into_iter().for_each( |
fold() |
对迭代器中的元素进行折叠,使用一个累加器。 | `let sum: i32 = (1...5).into_iter().fold(0, |
try_fold() |
对迭代器中的元素进行折叠,可能在遇到错误时提前返回。 | `let result: Result = (1...5).into_iter().try_fold(0, |
scan() |
对迭代器中的元素进行状态化的折叠。 | `let sum: Vec = (1...5).into_iter().scan(0, |
take() |
从迭代器中取出最多 n 个元素。 | let first_five = (1..10).into_iter().take(5).collect::<Vec<_>>() |
skip() |
跳过迭代器中的前 n 个元素。 | let after_five = (1..10).into_iter().skip(5).collect::<Vec<_>>() |
zip() |
将两个迭代器中的元素打包成元组。 | let zipped = (1..3).zip(&['a', 'b', 'c']).collect::<Vec<_>>() |
cycle() |
重复迭代器中的元素,直到无穷。 | let repeated = (1..3).into_iter().cycle().take(7).collect::<Vec<_>>() |
chain() |
连接多个迭代器。 | let combined = (1..3).chain(4..6).collect::<Vec<_>>() |
rev() |
反转迭代器中的元素顺序。 | let reversed = (1..4).into_iter().rev().collect::<Vec<_>>() |
enumerate() |
为迭代器中的每个元素添加索引。 | let enumerated = (1..4).into_iter().enumerate().collect::<Vec<_>>() |
peeking_take_while() |
取出满足条件的元素,同时保留迭代器的状态,可以继续取出后续元素。 | `let (first, rest) = (1...10).into_iter().peeking_take_while( |
step_by() |
按照指定的步长返回迭代器中的元素。 | let even_numbers = (0..10).into_iter().step_by(2).collect::<Vec<_>>() |
fuse() |
创建一个额外的迭代器,它在迭代器耗尽后仍然可以调用 next() 方法。 |
let mut iter = (1..5).into_iter().fuse(); while iter.next().is_some() {} |
inspect() |
在取出每个元素时执行一个闭包,但不改变元素。 | `let mut counter = 0; (1...5).into_iter().inspect( |
same_items() |
比较两个迭代器是否产生相同的元素序列。 | let equal = (1..5).into_iter().same_items((1..5).into_iter()); |