目录

Rust迭代器详解

文章目录

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());
本文是转载文章,点击查看原文
如有侵权,请联系 xyy@jishuzhan.net 删除
相关推荐
用户967151139167217 小时前
Rust 如何轻松实现 RTMP 流媒体推送?深入解析直播推流场景与解决方案
rust·ffmpeg
无名之逆17 小时前
Rust 开发提效神器:lombok-macros 宏库
服务器·开发语言·前端·数据库·后端·python·rust
s91236010117 小时前
rust 同时处理多个异步任务
java·数据库·rust
杰克逊的黑豹1 天前
不再迷茫:Rust, Zig, Go 和 C
c++·rust·go
Source.Liu1 天前
【学Rust写CAD】28 带 Alpha 通道的双线性插值函数(bilinear_interpolation_alpha.rs)
rust
Source.Liu1 天前
【学Rust写CAD】27 双线性插值函数(bilinear_interpolation.rs)
后端·rust·cad
yinhezhanshen1 天前
理解rust里面的copy和clone
开发语言·后端·rust
叠叠乐1 天前
rust Send Sync 以及对象安全和对象不安全
开发语言·安全·rust
niandb1 天前
The Rust Programming Language 学习 (九)
windows·rust
Source.Liu1 天前
【学Rust写CAD】26 图形像素获取(pixel_fetch.rs)
rust·cad