Rust 迭代器详解

2016-07-18 language rust

Rust 中的迭代器 (Iterator) 是一个强大灵活的工具,将数据和处理过程分离,可以简化对数组、Map、链表等的访问操作。实现时,采用惰性求值,有效降低非必要的性能开销。

简介

迭代器通过实现 std::iter::Iterator 特征定义,最基础的通过 next() 逐一返回下个元素,直到 None 结束。

pub trait Iterator {
    type Item;
    fn next(&mut self) -> Option<Self::Item>;
}

使用简介

如下以 Vector 为例介绍使用方法,很多其它集合也可以使用。

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

    // 创建借用迭代器,后面可以多次调用
    for v in v0.iter() {
        println!("{}", v);
    }
    let mut iter = v0.iter();
    while let Some(v) = iter.next() {
        println!("{}", v);
    }

    // 可变借用迭代器,可以修改内部成员
    for i in v0.iter_mut() {
        *i *= 2;
    }
    println!("{:?}", v0); // [2, 4, 6]

    // 所有权迭代器,后面不能再调用
    let mut iter = v0.into_iter();
    while let Some(v) = iter.next() {
        println!("{}", v);
    }
}

常用方法

使用最多的还是函数式编程方法,

fn main() {
    let v1: Vec<i32> = v0.iter().map(|x| x * x).collect();
    println!("{:?}", v1); // [1, 4, 9]

    let v1: Vec<&i32> = v0.iter().filter(|x| *x % 2 == 0).collect();
    println!("{:?}", v1); // [2]

    let v1: i32 = v0.iter().fold(0, |a, x| a + x);
    println!("{:?}", v1); // 6

    let v2 = vec![4, 5, 6];
    let v1: Vec<i32> = v0.iter().chain(v2.iter()).copied().collect();
    println!("{:?}", v1); // [1, 2, 3, 4, 5, 6]

    let v2 = vec!["Andy", "Tom", "Bob"];
    for (key, val) in v2.iter().zip(v0.iter()) {
        println!("{}={}", key, val); // Andy=1 Tome=2 Bob=3
    }
}

如下对常用的函数简单说明:

  • map 转换数据,通过闭包处理其中每个元素,然后返回新的含结果迭代器,原迭代器不变。
  • filter 过滤数据,同样通过闭包处理每个元素,当闭包返回 true 时对应元素包含在新的迭代器中。
  • fold 聚合数据,通过初始值和闭包循环调用每个元素,最终生成单一最终值。
  • chain 用于将两个迭代器链接在一起,会先遍历第一然后第二个。
  • zip 将两个迭代器同时进行遍历处理,每次同时返回对应的元素。
  • copied() 复制所有的元素,可以将 &T 转换为 T 类型,其作用与 map(|&x| x) 相同。

注意,闭包调用时,某些函数使用的是引用。