【Rust自学】13.8. 迭代器 Pt.4:创建自定义迭代器
13.8.0. 写在正文之前
Rust语言在设计过程中收到了很多语言的启发,而函数式编程对Rust产生了非常显著的影响。函数式编程通常包括通过将函数作为值传递给参数、从其他函数返回它们、将它们分配给变量以供以后执行等等。
在本章中,我们会讨论 Rust 的一些特性,这些特性与许多语言中通常称为函数式的特性相似:
- 闭包
- 迭代器(本文)
- 使用闭包和迭代器改进I/O项目
- 闭包和迭代器的性能
喜欢的话别忘了点赞、收藏加关注哦(加关注即可阅读全文),对接下来的教程有兴趣的可以关注专栏。谢谢喵!(=・ω・=)
13.8.1. 使用Iterator
trait创建自定义迭代器
最主要的步骤就只有一步:提供next
方法的实现。
看个例子:
做一个迭代器,从1遍历到5
struct Counter {
count: u32,
}
impl Counter {
fn new() -> Counter {
Counter { count: 0 }
}
}
impl Iterator for Counter {
type Item = u32;
fn next(&mut self) -> Option<u32> {
if self.count < 5 {
self.count += 1;
Some(self.count)
} else {
None
}
}
}
-
先创建一个结构体叫
Counter
,它有count
字段,用来存储迭代过程中所需要的数值,也就是迭代过程中的状态。这里count
字段不使用pub
而是设为私有是为了让Counter
结构体独立管理它的值。 -
然后在这个结构体上写了一个关联函数
new
用于创建新的实例,确保新实例从0开始。 -
下面就需要为
Counter
这个结构体实现Iterator
这个trait。Iterator
trait有一个关联类型type Item
还有一个next
方法。首先把关联类型指定为u32
,也就是写type Item = u32;
。这个语法在第19章会细讲,现在知道这个迭代器会返回u32
类型即可。 -
next
函数的返回类型是Option<Self::Item>
,由于上文写了关联类型指定为u32
,所以可以理解为Option<u32>
。当count
字段小于5的时候就继续加1,如果大于等于5就返回None
。这样就能保证从1到5的遍历。
现在我们来实现复杂一些的需求:
一样是Counter结构体,一个是从1到5,另一个是从2到5,把两个这样的迭代器的每对元素相乘,产生的新迭代器里的元素要求必须能被3整除,然后把这些元素的和返回
fn using_other_iterator_traits_methods() {
let sum: u32 = Counter::new()
.zip(Counter::new().skip(1))
.map(|(a, b)| a * b)
.filter({|x| x % 3 == 0})
.sum();
}
- 这里我分行写是因为链式调用写在一行太长了,如果链式调用的代码没多长就没必要分行写
zip
方法是把两个迭代器的每对元素和到一起形成新迭代器,这个新迭代器的元素就是元组,每个元组有两个值,分别来自两个迭代器。Counter::new()
就是建立一个从1到5的Counter
结构体,Counter::new().skip(1)
就是建立跳过1的Counter
结构体,也就是从2到5。把这两个结构体实例使用zip
和到一起就会形成如下表格的存储元组(Tuple)的迭代器:
Counter::new() | Counter::new().skip(1) | |
---|---|---|
Tuple 0 | 1 | 2 |
Tuple 1 | 2 | 3 |
Tuple 2 | 3 | 4 |
Tuple 3 | 4 | 5 |
PS:Counter::new() 不会遍历到5是因为Counter::new().skip(1) 在那时的值是None ,程序就不会再生成值 |
map
接收一个闭包,闭包作用于迭代器的每个元素。它把当前迭代器的每个元素给转换为另外一个元素,然后这些另外的元素就组成了一个新的迭代器。在这个例子中就是把迭代器存储的元组里的两个值相乘得到新的迭代器。filter
通过闭包把能整除3的值留下形成新的迭代器sum
消耗迭代器的所有元素,把其中的所有值相加求和
最后的结果应该是18
原文地址:https://blog.csdn.net/weixin_71793197/article/details/145239910
免责声明:本站文章内容转载自网络资源,如侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!