Rust iterator 迭代器

发布时间: 更新时间: 总字数:693 阅读时间:2m 作者: IP属地: 分享 复制网址

程序中,迭代器负责遍历每一个项。Rust的迭代器是惰性的,仅当调用迭代器的方法时才生效。

介绍

  • Rust 中所有的迭代器都实现了 iterator trait,其中 iterator trait 定义在标准库,定义如下:
pub trait Iterator {
    type Item;

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

    // ...
}

说明:

  • 实现 Iterator trait 需要定义一个 Item 类型,它用于 next 方法的返回类型
  • Iterator trait 需要实现 next 方法,next 方法如下:
    • 每次调用返回迭代器中的一项
    • 返回结果放在 Some 里
    • 迭代器结束,返回 None
  • 可以直接在迭代器上调用 next 方法
  • 消耗迭代器的方法:标准库中,Iterator trait 有一些带默认实现的方法,一些会调用 next,即为消耗性迭代器
    • 如:let x = vec![1, 2, 3]; let total:i32 = x.iter().sum();
  • 迭代器适配器:把迭代器转换为不同类型的迭代方法
  • Rust 中迭代器通过 零开销抽象(Zero-Cost Abstraction) 在抽象时不会引起额外的运行时开销

示例

fn main() {
  let x = vec![1, 2, 3];
  let mut x_iter = x.iter();  // next 时改变当前位置

  // for i in x_iter {
  //     println!("{}", i);
  // }

  assert_eq!(x_iter.next(), Some(&1));
  assert_eq!(x_iter.next(), Some(&2));

  let x: Vec<i32> = vec![1, 2, 3];
  let y: Vec<_> = x.iter().map(|x| x+1).collect();
  println!("x: {:?}, y:{:?}", x, y);  // x: [1, 2, 3], y:[2, 3, 4]
}

说明:

  • map 方法接收一个闭包,对所有值加一,并产生一个新的迭代器
  • collect 方法是消耗性迭代器,把结果收集到一个集合类型中
  • 上述示例采用了链式调用,可读性高

几种迭代方法

  • iter:在不可变引用上创建迭代器
  • into_iter:创建的迭代器会获得所有权
  • iter_mut:迭代可变的引用

使用闭包捕获环境

filter() 迭代器

  • 接收一个闭包:遍历迭代器的每一个元素,返回 bool 类型
    • true:当前元素会包含在 filter 产生的迭代器中
    • false:当前元素不会包含在 filter 产生的迭代器中

自定义迭代器

使用 Iterator trait 创建自定义迭代器需要实现 next 方法

struct Counter {
  count: u32,
}

impl Counter {
  fn new() -> Counter {
      Counter { count: 0 }
  }
}

impl Iterator for Counter {
  type Item = u32;

  fn next(&mut self) -> Option<Self::Item> {
      self.count += 1;
      Some(self.count)
  }
}

#[test]
fn test_counter() {
  let mut c = Counter::new();

  assert_eq!(c.next(), Some(1));
  assert_eq!(c.next(), Some(2));
  assert_eq!(c.next(), Some(3));
}
Home Archives Categories Tags Statistics
本文总阅读量 次 本站总访问量 次 本站总访客数