rust 迭代器iterator
1 原理
什么是迭代器?
- 迭代器是一个可以帮助你逐个访问集合(比如数组、列表或者其他数据结构)中元素的“指针”或者“工具”.
- 获取一个集合的迭代器后,你就拥有了可以逐个访问它的元素的能力
怎么设计?
- 只要给一个类型实现了能够逐个获取元素的能力, 它可以说就实现了迭代器
- trait 作为有可以共享代码的机制非常合适
- 设计这样一个trait
- 里面有一个需要实现的方法
next(),功能就是上面提到的逐个获取元素的能力 - 再设置一些默认的方法, 他们调用了next方法,做对应的功能处理,功能就共享给了所有实现该trait的类型
- 里面有一个需要实现的方法
- 只要类型实现了该next方法就可以了
所有迭代器都实现了 iterator trait
2 获取迭代器
fn main() {
let v1 = vec![1, 2, 3];
// v1_iter 本身取得的是 v1元素的不可变借用
let v1_iter = v1.iter();
// 这个mut 表示 该迭代器是可变的.
let mut v1_iter = v1.iter();
if let Some(b) = v1_iter.next() {
println!("{}", b); // 1
}
// 结果是: Iter([2, 3]), 这下能理解为啥上面需要 mut v1_iter
// 因为 next 方法会消耗 迭代器, 迭代器改变了
println!("{:?}", v1_iter);
// 继续调用next ,继续消耗迭代器
v1_iter.next();
v1_iter.next();
if let None = v1_iter.next() {
println!("没有元素后再调用next 返回None");
}
//结果是 Iter([])
println!("{:?}", v1_iter);
v1_iter.next(); // 不会报错
println!("{:?}", v1_iter);
let v1 = vec![1, 2, 3];
let v1_iter = v1.iter();
// for循环 会取得v1_iter的所有权
// 底层是调用了 next() 方法
for val in v1_iter {
println!("{}", val);
// v1_iter 已经被move了, 报错
println!("{:?}", v1_iter);
}
}fn main() {
let v1 = vec![1, 2, 3];
// v1.into_iter 看into_iter源码 impl<T, A: Allocator> IntoIterator for Vec<T, A>
// 我们平常都写Vec<i32> 这种, 第二个参数一般省略,A表示使用默认的用于存储向量元素的分配器
// 所以实际是调用 Vec::<i32>::into_iter(v1)
// 而 v1 是 move 型的类型
let v1_iter = v1.into_iter();
// println!("{:?}", v1); // 报错了, 提示已经被move
println!("{:?}", v1_iter2); // IntoIter([1, 2, 3])
}3 使用适配器
什么是适配器?
- 通过将原有数据进行转换调整以达到符合我们需求的一种”设备”
- rust上来讲就是迭代器iterator trait上定义的一些方法,用于对迭代器中可处理的数据进行操作
3.1 适配器的类别
Tip
- 消耗型适配器:
前面章节中我们使用的 next()就是消耗型 - 迭代器适配器: 它不会消耗迭代器,相反它是产生一个新的迭代器
迭代器适配器
消耗型适配器collect
fn main() {
let v1 = vec![1, 2, 3];
let v1_iter = v1.iter();
let v1_new_iter = v1_iter.map(|x| *x + 1);
// let data = v1_new_iter.collect::<Vec<_>>();
let data: Vec<_> = v1_new_iter.collect();
// 报错, collect 会消耗迭代器然后创建一个 vector 来保存数据
// 提示被move了
println!("{:?}", v1_new_iter);
println!("{:?}", data);3.2 常用适配器
3.2.1 sum
3.2.2 zip
3.2.3 map
use std::any::type_name;
fn print_type_of<T>(_: &T) {
println!("{}", type_name::<T>());
}
fn main() {
let v1 = vec![1, 2, 3];
for i in &v1 {
print_type_of(&i); // i 的类型是 &i32
println!("{}", *i);
}
let mut v1_iter = v1.iter();
if let Some(b) = v1_iter.next() {
print_type_of(&b); // &i32
}
println!("{:?}", v1);
let v1_iter = v1.iter();
// map 里闭包捕获的 v1的元素 是 &i32 类型
// 然后我们再看map的源码
// Iterator::map(self, FnMut(Self::Item) -> B),
// 所以首先 v1_iter被move 了,失效了
// v1_iter.next() 得到的每个 元素 是 &i32,
// FnMut(Self::Item) -> B 闭包参数是 Self.Item 就是迭代器逐个解析出的每个元素 &i32
// 所以传递给闭包 |x| *x + 1 的参数x
// 知道了x 是&i32, 所以我们才写 *x+1
// Vec<_> _ 表示Vec 元素类型不清楚
let f: Vec<_> = v1_iter.map(|x| *x + 1).collect();
println!("{:?}", f); // [2, 3, 4]
let a = vec![(1, 11), (2, 22), (3, 33)];
let b: Vec<_> = a.iter().map(|&(x, y)| x + 1).collect();
println!("{:?}", b);
}fn main() {
let v1 = vec![1, 2, 3];
for i in v1 {
print_type_of(&i); // i的类型是 i32
}
let v1 = vec![1, 2, 3];
let mut v1_iter = v1.into_iter();
if let Some(b) = v1_iter.next() {
print_type_of(&b); // i32
}
let v1 = vec![1, 2, 3];
let v1_iter = v1.into_iter();
let f: Vec<_> = v1_iter.map(|x| x + 1).collect();
println!("{:?}", f);
}use std::any::type_name;
fn print_type_of<T>(_: &T) {
println!("{}", type_name::<T>());
}
fn main() {
let mut v1 = vec![1, 2, 3];
for i in &mut v1 {
print_type_of(&i); // i 的类型是 &mut i32
println!("{}", *i);
}
let mut v1_iter = v1.iter_mut();
if let Some(b) = v1_iter.next() {
print_type_of(&b); // &mut i32
}
println!("{:?}", v1);
let v1_iter = v1.iter_mut();
let f: Vec<_> = v1_iter
.map(|x| {
*x = *x + 1; // 可变借用 ,所以可以修改
*x + 1
})
.collect();
println!("{:?}", f);
println!("{:?}", v1);
}3.2.4 filter
fn main() {
let v1: Vec<i32> = vec![1, 2, 3, 4, 5];
let v1_iter = v1.iter();
let two = 2;
// filter 将符合条件的返回 (true的情况)
// v1_iter 元素是 &i32,
// filter源码 定义的闭包类型是 FnMut(&Self::Item) -> bool
// 取的 &Self::Item -> & &i32, 所以 闭包里的x 的类型是 &&i32
let v_filtered: Vec<_> = v1_iter.filter(|x| **x >= two).collect();
println!("{:?}", v_filtered);
}3.2.5 any
3.2.6 find
3.2.7 position
3.2.8 enumerate
4 为自定义类型实现迭代器
随便写一个非常简单的例子
use std::iter::Iterator;
use std::result;
// 定义一个自定义类型 `Counter`
struct Counter {
start: u32,
end: u32,
}
// 不可变借用迭代器
struct CounterIter<'a> {
counter: &'a Counter,
curr: u32,
}
// 可变借用迭代器
struct CounterIterMut<'a> {
counter: &'a mut Counter,
curr: u32,
}
// 实现不可变借用迭代器
impl<'a> Iterator for CounterIter<'a> {
type Item = u32;
fn next(&mut self) -> Option<Self::Item> {
self.curr += 1;
if self.curr - 1 + self.counter.start <= self.counter.end {
Some(self.curr - 1 + self.counter.start)
} else {
None
}
}
}
// 实现可变借用迭代器
impl<'a> Iterator for CounterIterMut<'a> {
type Item = u32;
fn next(&mut self) -> Option<Self::Item> {
self.curr += 1;
if self.curr - 1 + self.counter.start <= self.counter.end {
Some(self.curr - 1 + self.counter.start)
} else {
None
}
}
}
// 为 `Counter` 类型增加方法以获取不同类型的迭代器
impl Counter {
// 获取不可变借用迭代器
fn iter(&self) -> CounterIter {
CounterIter {
counter: self,
curr: 0,
}
}
// 获取可变借用迭代器
fn iter_mut(&mut self) -> CounterIterMut {
CounterIterMut {
counter: self,
curr: 0,
}
}
// 获取所有权
fn into_iter(self) -> Self {
self
}
fn new(start: u32, end: u32) -> Self {
Counter { start, end }
}
}
// 为 `Counter` 实现 `Iterator` trait
impl Iterator for Counter {
// 定义迭代器返回的类型
type Item = u32;
// 实现 `next` 方法
fn next(&mut self) -> Option<Self::Item> {
// 检查计数器是否超过某个阈值
if self.start <= self.end {
self.start += 1;
Some(self.start - 1)
} else {
None
}
}
}
fn main() {
let counter = Counter::new(1, 4);
// 使用不可变借用迭代器
let mut iter = counter.iter();
println!("Immutable borrow iterator:");
while let Some(number) = iter.next() {
println!("{}", number);
}
let mut counter = Counter::new(2, 6);
// 使用可变借用迭代器
let mut iter_mut = counter.iter_mut();
println!("\nMutable borrow iterator:");
while let Some(number) = iter_mut.next() {
println!("{}", number);
}
// 使用获取所有权的迭代器
println!("\nOwned iterator:");
for number in counter.into_iter() {
println!("{}", number);
}
}