rust 迭代器iterator

Created

2024-05-14 09:00:30

Updated

2024-10-11 14:08:17

1 原理

什么是迭代器?
  • 迭代器是一个可以帮助你逐个访问集合(比如数组、列表或者其他数据结构)中元素的“指针”或者“工具”.
  • 获取一个集合的迭代器后,你就拥有了可以逐个访问它的元素的能力
怎么设计?
  • 只要给一个类型实现了能够逐个获取元素的能力, 它可以说就实现了迭代器
  • trait 作为有可以共享代码的机制非常合适
  • 设计这样一个trait
    • 里面有一个需要实现的方法next(),功能就是上面提到的逐个获取元素的能力
    • 再设置一些默认的方法, 他们调用了next方法,做对应的功能处理,功能就共享给了所有实现该trait的类型
  • 只要类型实现了该next方法就可以了

所有迭代器都实现了 iterator trait

Iterator trait 在标准库中的定义
pub trait Iterator {
    type Item;

    fn next(&mut self) -> Option<Self::Item>;

    // 其他方法都有默认实现
}

2 获取迭代器

let v1 = vec![1, 2, 3];
// 仅仅定义而没有使用它, 这样不会有任何的消耗
// 看ide的提示信息
v1.iter();
let v1_iter = v1.iter();
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 mut v1 = vec![1, 2, 3];
    // 取得v1的可变借用的迭代器
    let v1_iter = v1.iter_mut();
    println!("{:?}", v1_iter);
    let v11 = v1_iter.map(|x| {
        *x = *x + 1; // 修改v1元素的值,每个元素+1
        *x + 1
    });
    println!("{:?}", v11.collect::<Vec<_>>()); //  [3, 4, 5]
    println!("{:?}", v1); //[2, 3, 4]

}
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() 就是消耗型
  • 迭代器适配器: 它不会消耗迭代器,相反它是产生一个新的迭代器
迭代器适配器
fn main() {
    let v1 = vec![1, 2, 3];
    let v1_iter = v1.iter();
    // Iterator::map(self, f), 源码第一个参数是Self
    // 所以实际是 Iterator::map(v1_iter,|x|*x+1)
    // 迭代器是结构体, 是move类型
    let v1_new_iter = v1_iter.map(|x| *x + 1);
    //报错了. v1_iter 已经被move了,被 获取了所有权
    println!("{:?}", v1_iter);
}
消耗型适配器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

fn main() {
    let v1 = vec![1, 2, 3];

    let v1_iter = v1.iter();
    let total: i32 = v1_iter.sum();
    println!("{total}");
    // 调用sum 会获取v1_iter的所有权,所以报错了,提示move掉了
    // println!("{:?}", v1_iter);
}

3.2.2 zip

fn main() {
    let a = [1, 2, 3];
    let b = ['a', 'b', 'c'];
    // [(1, 'a'), (2, 'b'), (3, 'c')]
    let r=a.iter().zip(b.iter()).collect::<Vec<_>>();
    println!("{:?}", r);
}

3.2.3 map

fn map<B, F>(self, f: F) -> Map<Self, F>
    where
        Self: Sized,
        F: FnMut(Self::Item) -> B,
    {
        Map::new(self, f)
    }
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

#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_do_not_const_check]
fn filter<P>(self, predicate: P) -> Filter<Self, P>
where
    Self: Sized,
    P: FnMut(&Self::Item) -> bool,
{
    Filter::new(self, predicate)
}
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);
}
fn main() {
    let v1: Vec<i32> = vec![1, 2, 3, 4, 5];
    let v1_iter = v1.into_iter();
    let two = 2;
    let v_filtered: Vec<_> = v1_iter.filter(|x| *x >= two).collect();
    println!("{:?}", v_filtered);
}

3.2.5 any

fn main() {
    let v1 = vec![1, 2, 3];
    // any 如果有一个满足条件就返回true
    println!("2 in v1: {}", v1.iter().any(|x| *x == 2));
}

3.2.6 find

fn find<P>(&mut self, mut predicate: P) -> Option<Self::Item>
where
    Self: Sized,
    P: FnMut(&Self::Item) -> bool,
{
    while let Some(x) = self.next() {
        if predicate(&x) {
            return Some(x);
        }
    }
    None
}
fn main() {
    let v1 = vec![1, 2, 3];
    let mut iter = v1.iter();
    println!("Find 2 in v1: {:?}", iter.find(|&&x| x == 2));
}
fn main() {
    let v1 = vec![1, 2, 3];
    let mut iter = v1.into_iter();
    println!("Find 2 in v1: {:?}", iter.find(|&x| x == 2));
}

3.2.7 position

fn main() {
    let v1 = vec![1, 2, 6];
    // 符合条件的 索引 返回, 第一个元素 符合 *2=2
    let index = v1.iter().position(|&x| x * 2 == 2);
    println!("{:?}", index)  // Some(0) 第一个元素
}

3.2.8 enumerate

fn main(){
    let vowels = vec!['a', 'e', 'i', 'o', 'u'];
    // 产生一个新的迭代器, 每个元素是一个元组 (元素索引,元素)
    for (index, value) in vowels.iter().enumerate() {
        println!("{}: {}", index, value);
    }
}

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);
    }
}
Back to top