跳过正文

迭代器:iterator

··6282 字
Rust
目录
rust-lang - 这篇文章属于一个选集。
§ 13: 本文

在自定义类型上实现迭代器,如 impl Iterator for ReadDir ,也可以通过方法返回一个实现迭代器的类型(惯例是 Iter/IterMut/IntoIter)对象,惯例的方法名是:

  1. iter(&self): 返回的类型惯例是 Iter,迭代返回的是 &T 类型;
  2. iter_mut(&mut self): 返回的类型惯例是 IterMut,迭代返回的是 &mut T 类型;
  3. into_iter(self): 返回的迭代器对象惯例类型是 IntoIter,转移了被迭代对象的所有权,迭代返回的是 T 类型;

如果类型实现了 std::iter::IntoIterator trait 则称为可迭代对象,即可以使用 for-in 表达式来迭代对象,也可以给被迭代对象加 &obj 或 &mut obj 来让 for-in 使用 iter/iter_mut() 返回的对象:

Rust 为实现 Iterator 的类型自动实现了 IntoIterator

#[rustc_const_unstable(feature = "const_intoiterator_identity", issue = "90603")]
#[stable(feature = "rust1", since = "1.0.0")]
impl<I: Iterator> IntoIterator for I {
    type Item = I::Item;
    type IntoIter = I;

    #[inline]
    fn into_iter(self) -> I {
        self
    }
}

Vec<T>,[T; N],HashSet<T> 等实现了 IntoIterator

let mut v = vec![1, 2, 3];

for i in &v {
    println!("{i}")
}

for in in &mut v {
    println!("{i}")
}

for i in v { // v 被消耗
    println!("{i}");
}
// v 不可再访问

如果直接在自定义类型上实现迭代器,如 impl Iterator for ReadDir ,则在 ReadDir 上调用一些 self 迭代器方法,如 readDir.take(3) 后,readDir 将失效。但是如果在 iter()/iter_mut() 返回的迭代器对象上调用 take() 方法,消耗的是迭代器本身,原对象还可以正常访问. into_iter() 会转移对象所有权,迭代也是直接返回元素本身,所以 take() 返回并消耗对象。

消耗迭代器的方式:

  1. for-in 循环: 需要对象实现 std::iter::IntoIterator trait;
  2. Iterator trait 定义的泛型方法大部分都是消耗 self,如 iter.sum()/map() 等,所以 调用后迭代器对象所有权发生转移

for-in 使用 IntoIter 迭代器,它会消耗被迭代对象的元素。可以通过 &obj 或 &mut obj 来使用 Iter 或 IterMut 迭代器;

let mut array = [1, 2, 3];

// IntoIter
for n in array { // n 为 uint
 println!(n);
}
// 迭代后 array 不能再使用

// Iter
for n in &array { // n 为 &uint
  println!(n);
}
// 迭代后 array 可以使用

// IterMut
for n in &mut array { // n 为 &mut uint
  println!(n);
}

当迭代它们的引用类型时,返回的元素是引用类型,这是由于标准库 为 &HashMap/&mut HashMap/ HashMap 类型分别实现 了对应的 IntoIterator:

// https://doc.rust-lang.org/src/std/collections/hash/map.rs.html#2173-2182
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, K, V, S> IntoIterator for &'a HashMap<K, V, S> {
    type Item = (&'a K, &'a V);
    // Iter 是 HashMap 定义的实现 Iterator trait 的类型
    type IntoIter = Iter<'a, K, V>;

    #[inline]
    #[rustc_lint_query_instability]
    fn into_iter(self) -> Iter<'a, K, V> {
        self.iter()
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, K, V, S> IntoIterator for &'a mut HashMap<K, V, S> {
    type Item = (&'a K, &'a mut V);
    // IterMut 是 HashMap 定义的实现 Iterator trait 的类型
    type IntoIter = IterMut<'a, K, V>;

    #[inline]
    #[rustc_lint_query_instability]
    fn into_iter(self) -> IterMut<'a, K, V> {
        self.iter_mut()
    }
}

for-in 迭代器也可以使用 pattern match 来析构迭代变量:

let mut array = [(1, 2, 3), (4, 5, 6)];
for (a, b, &c) in &array { // &c 匹配引用类型,所以 c 是引用类型
    println!("{} {} {}", a, b, *c);
}

迭代器适配器(iterator adaptor)是 Iterator trait 的方法,它一般会消耗旧 Iterator (这些适配器方法的输入绝大大部分是 self)并返回新的 Iterator。Iterator 都是 lazy 的,必须被消耗时才能执行,如调用 collect() ;

  • collect() 返回的是一个实现了 FromIterator<Self::Item> trait 的对象;
  • 标准库的容器类型,如 Vec/HastSet/HashMap 都实现了 FromIterator trait,可以从可迭代对象生成容器元素。
#[derive(PartialEq, Debug)]
struct Shoe {
    size: u32,
    style: String,
}

// 由于返回一个 Vec<Shoe> ,所以需要 into_iter() 返回的 IntoIter 迭代器。
fn shoes_in_size(shoes: Vec<Shoe>, shoe_size: u32) -> Vec<Shoe> {
    shoes.into_iter().filter(|s| s.size == shoe_size).collect()
}

// Vec<T> 实现了 FromIterator<T> trait, 所以 collect() 方法可以返回该类型对象:
let v1: Vec<i32> = vec![1, 2, 3];
// iter() 返回 &32, 所以最终 collect() 返回的是 &i32.
let v2: Vec<&i32> = v1.iter().map(|x| x + 1).collect();
assert_eq!(v2, vec![2, 3, 4]);

// 另一个例子
impl Config {
    // Vec<String> 实现了该 trait
    pub fn build(mut args: impl Iterator<Item = String>,)
        -> Result<Config, &'static str> {
        args.next();

        let query = match args.next() {
            Some(arg) => arg,
            None => return Err("Didn't get a query string"),
        };

        let file_path = match args.next() {
            Some(arg) => arg,
            None => return Err("Didn't get a file path"),
        };

        let ignore_case = env::var("IGNORE_CASE").is_ok();

        Ok(Config {
            query,
            file_path,
            ignore_case,
        })
    }
}

fn main() {
    let config = Config::build(env::args()).unwrap_or_else(|err| {
        eprintln!("Problem parsing arguments: {err}");
        process::exit(1);
    });

    // --snip--
}

Option/Result 是 enum 类型,也支持迭代(实现了 IntoIterator),效果为 1 个或 0 个元素:

  • filter_map(): 先执行 map 返回 Option,然后再 filter 出结果为 Some 的元素,类似于这种双功能的方法,都是先执行后一个功能,对结果再执行前一个功能。例如 flat_map() 先对元素进行 map F 操作,F 返回一个迭代器,然后对各 map 结果迭代器进行 flat 操作。
let turing = Some("Turing");
let mut logicians = vec!["Curry", "Kleene", "Markov"];
// Option 实现了 IntoIterator, 因此可以传入 .extend() 方法中;
logicians.extend(turing);

// 也可以传入 chain() 方法中
let turing = Some("Turing");
let logicians = vec!["Curry", "Kleene", "Markov"];
for logician in logicians.iter().chain(turing.iter()) {
    println!("{logician} is a logician");
}

Rust range 表达式是一系列支持迭代的 std::ops::RangeXX struct 类型的语法糖:

1..2;   // std::ops::Range
3..;    // std::ops::RangeFrom
..4;    // std::ops::RangeTo
..;     // std::ops::RangeFull
5..=6;  // std::ops::RangeInclusive
..=7;   // std::ops::RangeToInclusive

let x = std::ops::Range {start: 0, end: 10};
let y = 0..10;
assert_eq!(x, y);

1 迭代器方法
#

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

// 返回下一个 N 个元素的数组,N 的数量可以指定或推导
fn next_chunk<const N: usize>( &mut self )
  -> Result<[Self::Item; N], IntoIter<Self::Item, N>> where Self: Sized
    let mut iter = "lorem".chars();
    // N is inferred as 2
    assert_eq!(iter.next_chunk().unwrap(), ['l', 'o']);
    // N is inferred as 3
    assert_eq!(iter.next_chunk().unwrap(), ['r', 'e', 'm']);
    // N is explicitly 4
    assert_eq!(iter.next_chunk::<4>().unwrap_err().as_slice(), &[]);
    let quote = "not all those who wander are lost";
    // 自动推导
    let [first, second, third] = quote.split_whitespace().next_chunk().unwrap();
    assert_eq!(first, "not");
    assert_eq!(second, "all");
    assert_eq!(third, "those");

// 返回迭代器中剩下元素的下界和上界
fn size_hint(&self) -> (usize, Option<usize>) { ... }

// 返回迭代器中元素数量(消耗)
fn count(self) -> usize where Self: Sized { ... }

// 返回最后一个元素(消耗)
fn last(self) -> Option<Self::Item> where Self: Sized { ... }

// 前进迭代器 n 个元素
fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> { ... }
    #![feature(iter_advance_by)]
    use std::num::NonZeroUsize;
    let a = [1, 2, 3, 4];
    let mut iter = a.iter();
    assert_eq!(iter.advance_by(2), Ok(()));
    assert_eq!(iter.next(), Some(&3));
    assert_eq!(iter.advance_by(0), Ok(()));
    // only `&4` was skipped
    assert_eq!(iter.advance_by(100), Err(NonZeroUsize::new(99).unwrap()));

// 返回第 n 个元素(0 开始,不消耗迭代器所有权,可以多次调用)
fn nth(&mut self, n: usize) -> Option<Self::Item> { ... }
    let a = [1, 2, 3];
    let mut iter = a.iter();
    assert_eq!(iter.nth(1), Some(&2));
    // 调用 nth(n) 多次并不重复返回
    assert_eq!(iter.nth(1), None);
    assert_eq!(iter.nth(10), None);

// 返回一个新的迭代器,每次返回原始迭代器的 +step 后的元素
fn step_by(self, step: usize) -> StepBy<Self> where Self: Sized { ... }
    let a = [0, 1, 2, 3, 4, 5];
    let mut iter = a.iter().step_by(2);
    assert_eq!(iter.next(), Some(&0)); // 第一个元素
    assert_eq!(iter.next(), Some(&2)); // +2
    assert_eq!(iter.next(), Some(&4));
    assert_eq!(iter.next(), None);

// 将两个迭代器合并为一个,先迭代自身再迭代传入的 other, 迭代的元素 Item 类型要一致
fn chain<U>(self, other: U) -> Chain<Self, <U as IntoIterator>::IntoIter> where Self: Sized, U: IntoIterator<Item = Self::Item>
    let a1 = [1, 2, 3];
    let a2 = [4, 5, 6];
    let mut iter = a1.iter().chain(a2.iter());
    assert_eq!(iter.next(), Some(&1));
    assert_eq!(iter.next(), Some(&2));
    assert_eq!(iter.next(), Some(&3));
    assert_eq!(iter.next(), Some(&4));
    assert_eq!(iter.next(), Some(&5));
    assert_eq!(iter.next(), Some(&6));
    assert_eq!(iter.next(), None);

// 从两个迭代器返回一个新的迭代器,每次各返回一个值,直到某个迭代器完成
fn zip<U>(self, other: U) -> Zip<Self, <U as IntoIterator>::IntoIter> where Self: Sized, U: IntoIterator
    let a1 = [1, 2, 3];
    let a2 = [4, 5, 6];
    let mut iter = a1.iter().zip(a2.iter());
    assert_eq!(iter.next(), Some((&1, &4)));
    assert_eq!(iter.next(), Some((&2, &5)));
    assert_eq!(iter.next(), Some((&3, &6)));
    assert_eq!(iter.next(), None);
    let enumerate: Vec<_> = "foo".chars().enumerate().collect();
    let zipper: Vec<_> = (0..).zip("foo".chars()).collect();
    assert_eq!((0, 'f'), enumerate[0]);
    assert_eq!((0, 'f'), zipper[0]);
    assert_eq!((1, 'o'), enumerate[1]);
    assert_eq!((1, 'o'), zipper[1]);
    assert_eq!((2, 'o'), enumerate[2]);
    assert_eq!((2, 'o'), zipper[2]);

// 在迭代器元素间插入一个 separator 元素(需要实现 Clone)
fn intersperse(self, separator: Self::Item) -> Intersperse<Self> where Self: Sized, Self::Item: Clone
    #![feature(iter_intersperse)]
    let hello = ["Hello", "World", "!"].iter().copied().intersperse(" ").collect::<String>();
    assert_eq!(hello, "Hello World !");
    let mut a = [0, 1, 2].iter().intersperse(&100);
    assert_eq!(a.next(), Some(&0));   // The first element from `a`.
    assert_eq!(a.next(), Some(&100)); // The separator.
    assert_eq!(a.next(), Some(&1));   // The next element from `a`.
    assert_eq!(a.next(), Some(&100)); // The separator.
    assert_eq!(a.next(), Some(&2));   // The last element from `a`.
    assert_eq!(a.next(), None);       // The iterator is finished.

// 使用指定的闭包函数插入分隔符
fn intersperse_with<G>(self, separator: G) -> IntersperseWith<Self, G> where Self: Sized, G: FnMut() -> Self::Item

// 使用指定的闭包函数来处理每一个元素(消耗迭代器),结果形成另一个可迭代对象
fn map<B, F>(self, f: F) -> Map<Self, F> where Self: Sized, F: FnMut(Self::Item) -> B
    let a = [1, 2, 3];
    let mut iter = a.iter().map(|x| 2 * x);
    assert_eq!(iter.next(), Some(2));
    assert_eq!(iter.next(), Some(4));
    assert_eq!(iter.next(), Some(6));
    assert_eq!(iter.next(), None);

// 对每一个元素调用指定的闭包函数(消耗迭代器)
fn for_each<F>(self, f: F) where Self: Sized, F: FnMut(Self::Item) { ... }
    use std::sync::mpsc::channel;
    let (tx, rx) = channel();
    (0..5).map(|x| x * 2 + 1).for_each(move |x| tx.send(x).unwrap());
    let v: Vec<_> = rx.iter().collect();
    assert_eq!(v, vec![1, 3, 5, 7, 9]);

// 使用 predicate 过滤元素,返回为 true 的元素的迭代器(predicate 的参数是元素的借用)
fn filter<P>(self, predicate: P) -> Filter<Self, P> where Self: Sized, P: FnMut(&Self::Item) -> bool
    let a = [0, 1, 2];
    // **x 需要两个 *,和 map() 不同,filter 闭包函数的参数是 &T 类型。
    let mut iter = a.iter().filter(|x| **x > 1);
    assert_eq!(iter.next(), Some(&2));
    assert_eq!(iter.next(), None);
    let a = [0, 1, 2];
    let mut iter = a.iter().filter(|&x| *x > 1); // both & and *
    assert_eq!(iter.next(), Some(&2));
    assert_eq!(iter.next(), None);
    let a = [0, 1, 2];
    let mut iter = a.iter().filter(|&&x| x > 1); // two &s
    assert_eq!(iter.next(), Some(&2));
    assert_eq!(iter.next(), None);

// 对迭代元素值先执行 f 闭包(map),返回结果为 Some(value) 的 value(filter)迭代器
fn filter_map<B, F>(self, f: F) -> FilterMap<Self, F> where Self: Sized, F: FnMut(Self::Item) -> Option<B>
    let a = ["1", "two", "NaN", "four", "5"];
    let mut iter = a.iter().filter_map(|s| s.parse().ok()); // Result 的 ok() 方法返回 Option
    assert_eq!(iter.next(), Some(1));
    assert_eq!(iter.next(), Some(5));
    assert_eq!(iter.next(), None);
    // 等效为 filter().map()
    let a = ["1", "two", "NaN", "four", "5"];
    let mut iter = a.iter().map(|s| s.parse()).filter(|s| s.is_ok()).map(|s| s.unwrap());
    assert_eq!(iter.next(), Some(1));
    assert_eq!(iter.next(), Some(5));
    assert_eq!(iter.next(), None);

// 返回 (i, value) 的迭代器,i 的类型为 usize
fn enumerate(self) -> Enumerate<Self> where Self: Sized { ... }
    let a = ['a', 'b', 'c'];
    let mut iter = a.iter().enumerate();
    assert_eq!(iter.next(), Some((0, &'a')));
    assert_eq!(iter.next(), Some((1, &'b')));
    assert_eq!(iter.next(), Some((2, &'c')));
    assert_eq!(iter.next(), None);

// 返回一个迭代器,它的 peek/peek_mut() 返回下一个迭代元素,但是并不消费迭代元素
fn peekable(self) -> Peekable<Self> where Self: Sized
    let xs = [1, 2, 3];
    let mut iter = xs.iter().peekable();
    // peek() lets us see into the future
    assert_eq!(iter.peek(), Some(&&1));
    assert_eq!(iter.next(), Some(&1));
    assert_eq!(iter.next(), Some(&2));
    // we can peek() multiple times, the iterator won't advance
    assert_eq!(iter.peek(), Some(&&3));
    assert_eq!(iter.peek(), Some(&&3));
    assert_eq!(iter.next(), Some(&3));
    // after the iterator is finished, so is peek()
    assert_eq!(iter.peek(), None);
    assert_eq!(iter.next(), None);

// 迭代时一直忽略元素,直到 predicte 返回 false(包含返回 false 的元素)
fn skip_while<P>(self, predicate: P) -> SkipWhile<Self, P> where Self: Sized, P: FnMut(&Self::Item) -> bool
    let a = [-1i32, 0, 1];
    let mut iter = a.iter().skip_while(|x| x.is_negative());
    assert_eq!(iter.next(), Some(&0));
    assert_eq!(iter.next(), Some(&1));
    assert_eq!(iter.next(), None);
    // 注意:一旦 predicate 返回 false,后续就不再对元素进行判断
    let a = [-1, 0, 1, -2];
    let mut iter = a.iter().skip_while(|x| **x < 0);
    assert_eq!(iter.next(), Some(&0));
    assert_eq!(iter.next(), Some(&1));
    // while this would have been false, since we already got a false,
    // skip_while() isn't used any more
    assert_eq!(iter.next(), Some(&-2));
    assert_eq!(iter.next(), None);

// 当 predicate 返回 true 时,返回元素。但是一旦返回 false,则忽略后续的元素。
fn take_while<P>(self, predicate: P) -> TakeWhile<Self, P> where Self: Sized, P: FnMut(&Self::Item) -> bool
    let a = [-1i32, 0, 1];
    let mut iter = a.iter().take_while(|x| x.is_negative());
    assert_eq!(iter.next(), Some(&-1));
    assert_eq!(iter.next(), None);
    // 一旦 predicate 返回 false,就不再返回后续的元素。
    let a = [-1, 0, 1, -2];
    let mut iter = a.iter().take_while(|x| **x < 0);
    assert_eq!(iter.next(), Some(&-1));
    // We have more elements that are less than zero, but since we already
    // got a false, take_while() isn't used any more
    assert_eq!(iter.next(), None);

// 持续对每个元素应用 predicate,直到它返回 None(predicate 返回 some 时继续)
fn map_while<B, P>(self, predicate: P) -> MapWhile<Self, P> where Self: Sized, P: FnMut(Self::Item) -> Option<B>
    let a = [-1i32, 4, 0, 1];
    let mut iter = a.iter().map_while(|x| 16i32.checked_div(*x));
    assert_eq!(iter.next(), Some(-16));
    assert_eq!(iter.next(), Some(4));
    assert_eq!(iter.next(), None);

// 忽略前 n 个元素
fn skip(self, n: usize) -> Skip<Self> where Self: Sized { ... }
    let a = [1, 2, 3];
    let mut iter = a.iter().skip(2);
    assert_eq!(iter.next(), Some(&3));
    assert_eq!(iter.next(), None);

// 只获取前 n 个元素
fn take(self, n: usize) -> Take<Self> where Self: Sized { ... }
    let v = [1, 2];
    let mut iter = v.into_iter().take(5);
    assert_eq!(iter.next(), Some(1));
    assert_eq!(iter.next(), Some(2));
    assert_eq!(iter.next(), None);

// 返回一个迭代器,每次迭代返回 f 闭包执行的结果 Some,当闭包 f 返回 None 时停止迭代
fn scan<St, B, F>(self, initial_state: St, f: F) -> Scan<Self, St, F> where Self: Sized, F: FnMut(&mut St, Self::Item) -> Option<B>
    let a = [1, 2, 3, 4];
    let mut iter = a.iter().scan(1, |state, &x| {
        // each iteration, we'll multiply the state by the element ...
        *state = *state * x;
        // ... and terminate if the state exceeds 6
        if *state > 6 {
            return None;
        }
        // ... else yield the negation of the state
        Some(-*state)
    });
    assert_eq!(iter.next(), Some(-1));
    assert_eq!(iter.next(), Some(-2));
    assert_eq!(iter.next(), Some(-6));
    assert_eq!(iter.next(), None);

// 先对元素进行 map F 操作,F 返回一个迭代器,然后对各 map 结果迭代器进行 flat
fn flat_map<U, F>(self, f: F) -> FlatMap<Self, U, F> where Self: Sized, U: IntoIterator, F: FnMut(Self::Item) -> U
    let words = ["alpha", "beta", "gamma"];
    // chars() returns an iterator
    let merged: String = words.iter().flat_map(|s| s.chars()).collect();
    assert_eq!(merged, "alphabetagamma");

// 返回一个将可迭代元素打平的迭代器
fn flatten(self) -> Flatten<Self> where Self: Sized, Self::Item: IntoIterator
    let data = vec![vec![1, 2, 3, 4], vec![5, 6]];
    let flattened = data.into_iter().flatten().collect::<Vec<u8>>();
    assert_eq!(flattened, &[1, 2, 3, 4, 5, 6]);

    // Option/Result 也是可迭代的,可以使用 flatten() 来过滤掉 None 和 Err
    let options = vec![Some(123), Some(321), None, Some(231)];
    let flattened_options: Vec<_> = options.into_iter().flatten().collect();
    assert_eq!(flattened_options, vec![123, 321, 231]);

    let results = vec![Ok(123), Ok(321), Err(456), Ok(231)];
    let flattened_results: Vec<_> = results.into_iter().flatten().collect();
    assert_eq!(flattened_results, vec![123, 321, 231]);

    // flatten 只会打平一级
    let d3 = [[[1, 2], [3, 4]], [[5, 6], [7, 8]]];
    let d2 = d3.iter().flatten().collect::<Vec<_>>();
    assert_eq!(d2, [&[1, 2], &[3, 4], &[5, 6], &[7, 8]]);

    let d1 = d3.iter().flatten().flatten().collect::<Vec<_>>();
    assert_eq!(d1, [&1, &2, &3, &4, &5, &6, &7, &8]);

// 先将元素按照 N 分组 window(window 间元素有重合),然后再对每个 window 的元素执行 f
// 闭包,如果元素少于 N 则返回空迭代器
// 闭包的参数类型是数组引用
fn map_windows<F, R, const N: usize>(self, f: F) -> MapWindows<Self, F, N> where Self: Sized, F: FnMut(&[Self::Item; N]) -> R
    #![feature(iter_map_windows)]
    let strings = "abcd".chars()
        .map_windows(|[x, y]| format!("{}+{}", x, y)) //  &['a', 'b'], &['b', 'c'] and &['c', 'd']
        .collect::<Vec<String>>();
    assert_eq!(strings, vec!["a+b", "b+c", "c+d"]);
    #![feature(iter_map_windows)]
    let mut it = [0.5, 1.0, 3.5, 3.0, 8.5, 8.5, f32::NAN].iter()
        .map_windows(|[a, b]| a <= b);
    assert_eq!(it.next(), Some(true));  // 0.5 <= 1.0
    assert_eq!(it.next(), Some(true));  // 1.0 <= 3.5
    assert_eq!(it.next(), Some(false)); // 3.5 <= 3.0
    assert_eq!(it.next(), Some(true));  // 3.0 <= 8.5
    assert_eq!(it.next(), Some(true));  // 8.5 <= 8.5
    assert_eq!(it.next(), Some(false)); // 8.5 <= NAN
    assert_eq!(it.next(), None);

// 返回一个新迭代器,终止于原迭代器返回的第一个 None,用于防止原迭代器不规范的实现
fn fuse(self) -> Fuse<Self> where Self: Sized

// 对迭代的每一个元素执行闭包操作
fn inspect<F>(self, f: F) -> Inspect<Self, F> where Self: Sized, F: FnMut(&Self::Item)
    // let's add some inspect() calls to investigate what's happening
    let sum = a.iter()
        .cloned()
        .inspect(|x| println!("about to filter: {x}"))
        .filter(|x| x % 2 == 0)
        .inspect(|x| println!("made it through filter: {x}"))
        .fold(0, |sum, i| sum + i);
    println!("{sum}");

// borrow 但不转移 Self,迭代器可以继续使用
fn by_ref(&mut self) -> &mut Self where Self: Sized
    let mut words = ["hello", "world", "of", "Rust"].into_iter();
    // Take the first two words.
    let hello_world: Vec<_> = words.by_ref().take(2).collect(); // 不转移  words
    assert_eq!(hello_world, vec!["hello", "world"]);
    // Collect the rest of the words. We can only do this because we used `by_ref` earlier.
    let of_rust: Vec<_> = words.collect(); // words 还可以继续使用
    assert_eq!(of_rust vec!["of", "Rust"]);

// 使用 B 的 FromIterator trait 来从自身迭代器元素生成 B 类型对象
fn collect<B>(self) -> B where B: FromIterator<Self::Item>, Self: Sized
    let doubled: Vec<i32> = a.iter() .map(|&x| x * 2) .collect();
    assert_eq!(vec![2, 4, 6], doubled);
    let a = [1, 2, 3];
    let doubled = a.iter().map(|x| x * 2).collect::<Vec<i32>>();
    assert_eq!(vec![2, 4, 6], doubled);
    // 检查 Result 列表
    let results = [Ok(1), Err("nope"), Ok(3), Err("bad")];
    let result: Result<Vec<_>, &str> = results.iter().cloned().collect();
    // gives us the first error
    assert_eq!(Err("nope"), result);
    let results = [Ok(1), Ok(3)];
    let result: Result<Vec<_>, &str> = results.iter().cloned().collect();
    // gives us the list of answers
    assert_eq!(Ok(vec![1, 3]), result);

// 允许失败的 collect,主要用于将迭代元素是 Option<T> 转换为 Option<Collector<T>> 类型
    fn try_collect<B>( &mut self ) -> ::TryType where Self: Sized, Self::Item: Try, <Self::Item as Try>::Residual: Residual<B>, B: FromIterator<<Self::Item as Try>::Output>
    #![feature(iterator_try_collect)]
    let u = vec![Some(1), Some(2), Some(3)];
    let v = u.into_iter().try_collect::<Vec<i32>>();
    assert_eq!(v, Some(vec![1, 2, 3]));

// 将 Self 迭代的元素添加到传入的 collection 中
fn collect_into<E>(self, collection: &mut E) -> &mut E where E: Extend<Self::Item>, Self: Sized
    #![feature(iter_collect_into)]
    let a = [1, 2, 3];
    let mut vec: Vec::<i32> = vec![0, 1];
    a.iter().map(|&x| x * 2).collect_into(&mut vec);
    a.iter().map(|&x| x * 10).collect_into(&mut vec);
    assert_eq!(vec, vec![0, 1, 2, 4, 6, 10, 20, 30]);

// 使用 f 将迭代器元素分两组,分别为返回 true/false 的元素
fn partition<B, F>(self, f: F) -> (B, B) where Self: Sized, B: Default + Extend<Self::Item>, F: FnMut(&Self::Item) -> bool
    let a = [1, 2, 3];
    let (even, odd): (Vec<_>, Vec<_>) = a
        .into_iter()
        .partition(|n| n % 2 == 0);
    assert_eq!(even, vec![2]);
    assert_eq!(odd, vec![1, 3]);

// 原地修改 self,前一半部分为 true,后一半为 false,返回 true 元素数量
fn partition_in_place<'a, T, P>(self, predicate: P) -> usize where T: 'a, Self: Sized + DoubleEndedIterator<Item = &'a mut T>, P: FnMut(&T) -> bool
    #![feature(iter_partition_in_place)]
    let mut a = [1, 2, 3, 4, 5, 6, 7];
    // Partition in-place between evens and odds
    let i = a.iter_mut().partition_in_place(|&n| n % 2 == 0);
    assert_eq!(i, 3);
    assert!(a[..i].iter().all(|&n| n % 2 == 0)); // evens
    assert!(a[i..].iter().all(|&n| n % 2 == 1)); // odds

// 返回 self 是否按照 predicate 排序
fn is_partitioned<P>(self, predicate: P) -> bool where Self: Sized, P: FnMut(Self::Item) -> bool
    #![feature(iter_is_partitioned)]
    assert!("Iterator".chars().is_partitioned(char::is_uppercase));
    assert!(!"IntoIterator".chars().is_partitioned(char::is_uppercase));

fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R where Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try<Output = B>
fn try_for_each<F, R>(&mut self, f: F) -> R where Self: Sized, F: FnMut(Self::Item) -> R, R: Try<Output = ()>
// 将迭代器值按照 F 进行聚合,同时传入初始值,返回最后的结果
fn fold<B, F>(self, init: B, f: F) -> B where Self: Sized, F: FnMut(B, Self::Item) -> B { ... }
    let a = [1, 2, 3];
    // the sum of all of the elements of the array
    let sum = a.iter().fold(0, |acc, x| acc + x);
    assert_eq!(sum, 6);

// 和 fold 类似,但是使用第一个值作为初始值
fn reduce<F>(self, f: F) -> Option<Self::Item> where Self: Sized, F: FnMut(Self::Item, Self::Item) -> Self::Item
fn try_reduce<F, R>( &mut self, f: F ) -> >::TryType where Self: Sized, F: FnMut(Self::Item, Self::Item) -> R, R: Try<Output = Self::Item>, <R as Try>::Residual: Residual<Option<Self::Item>>
    let reduced: i32 = (1..10).reduce(|acc, e| acc + e).unwrap();
    assert_eq!(reduced, 45);
    // Which is equivalent to doing it with `fold`:
    let folded: i32 = (1..10).fold(0, |acc, e| acc + e);
    assert_eq!(reduced, folded);

// 迭代的所有元素满足 f
fn all<F>(&mut self, f: F) -> bool where Self: Sized, F: FnMut(Self::Item) -> bool { ... }

// 迭代的任一元素满足 f
fn any<F>(&mut self, f: F) -> bool where Self: Sized, F: FnMut(Self::Item) -> bool { ... }

// 返回 predicate 为 true 的第一个元素或 None;对比:position() 返回元素的 index
fn find<P>(&mut self, predicate: P) -> Option<Self::Item> where Self: Sized, P: FnMut(&Self::Item) -> bool
    let a = [1, 2, 3];
    let mut iter = a.iter();
    assert_eq!(iter.find(|&&x| x == 2), Some(&2));
    // we can still use `iter`, as there are more elements.
    assert_eq!(iter.next(), Some(&3));

// 对迭代器元素执行 f,返回第一个结果为 Some(B) 的 Option<B>,等效于 iter.filter_map(f).next().
fn find_map<B, F>(&mut self, f: F) -> Option<B> where Self: Sized, F: FnMut(Self::Item) -> Option<B>
    let a = ["lol", "NaN", "2", "5"];
    let first_number = a.iter().find_map(|s| s.parse().ok());
    assert_eq!(first_number, Some(2));

fn try_find<F, R>( &mut self, f: F ) -> >::TryType where Self: Sized, F: FnMut(&Self::Item) -> R, R: Try<Output = bool>, <R as Try>::Residual: Residual<Option<Self::Item>> { ... }

// 查找满足 predicate 的元素,返回它的 index。对比:find() 返回元素本身。
fn position<P>(&mut self, predicate: P) -> Option<usize> where Self: Sized, P: FnMut(Self::Item) -> bool
fn rposition<P>(&mut self, predicate: P) -> Option<usize> where P: FnMut(Self::Item) -> bool, Self: Sized + ExactSizeIterator + DoubleEndedIterator
    let a = [1, 2, 3];
    assert_eq!(a.iter().position(|&x| x == 2), Some(1));
    assert_eq!(a.iter().position(|&x| x == 5), None);

fn max(self) -> Option<Self::Item> where Self: Sized, Self::Item: Ord
fn min(self) -> Option<Self::Item> where Self: Sized, Self::Item: Ord
// 根据 f 闭包返回的结果来找最大值
    fn max_by_key<B, F>(self, f: F) -> Option<Self::Item> where B: Ord, Self: Sized, F: FnMut(&Self::Item) -> B
    let a = [-3_i32, 0, 1, 5, -10];
    assert_eq!(*a.iter().max_by_key(|x| x.abs()).unwrap(), -10);

// 根据 compare 函数的返回值来找最大值
fn max_by<F>(self, compare: F) -> Option<Self::Item> where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Ordering
    let a = [-3_i32, 0, 1, 5, -10];
    assert_eq!(*a.iter().max_by(|x, y| x.cmp(y)).unwrap(), 5);

fn min_by_key<B, F>(self, f: F) -> Option<Self::Item> where B: Ord, Self: Sized, F: FnMut(&Self::Item) -> B
fn min_by<F>(self, compare: F) -> Option<Self::Item> where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Ordering { ... }

// 返回迭代器的反向迭代器
fn rev(self) -> Rev<Self> where Self: Sized + DoubleEndedIterator
    let a = [1, 2, 3];
    let mut iter = a.iter().rev();
    assert_eq!(iter.next(), Some(&3));
    assert_eq!(iter.next(), Some(&2));
    assert_eq!(iter.next(), Some(&1));
    assert_eq!(iter.next(), None);

// 迭代器迭代返回 (A, B), 然后返回两个分别是 A 、B 聚合后的对象。A,B
fn unzip<A, B, FromA, FromB>(self) -> (FromA, FromB) where FromA: Default + Extend<A>, FromB: Default + Extend<B>, Self: Sized + Iterator<Item = (A, B)>
    let a = [(1, 2), (3, 4), (5, 6)];
    let (left, right): (Vec<_>, Vec<_>) = a.iter().cloned().unzip();
    assert_eq!(left, [1, 3, 5]);
    assert_eq!(right, [2, 4, 6]);
    // you can also unzip multiple nested tuples at once
    let a = [(1, (2, 3)), (4, (5, 6))];
    let (x, (y, z)): (Vec<_>, (Vec<_>, Vec<_>)) = a.iter().cloned().unzip();
    assert_eq!(x, [1, 4]);
    assert_eq!(y, [2, 5]);
    assert_eq!(z, [3, 6]);

// 使用元素的 Copy 对象来返回一个新的迭代器,特别适合从 &T 返回 T
fn copied<'a, T>(self) -> Copied<Self> where T: 'a + Copy, Self: Sized + Iterator<Item = &'a T>
    let a = [1, 2, 3];
    let v_copied: Vec<_> = a.iter().copied().collect();
    // copied is the same as .map(|&x| x)
    let v_map: Vec<_> = a.iter().map(|&x| x).collect();
    assert_eq!(v_copied, vec![1, 2, 3]);
    assert_eq!(v_map, vec![1, 2, 3]);

// 使用元素的 Clone 对象来返回一个新的迭代器,适合 从 &T 返回 T
fn cloned<'a, T>(self) -> Cloned<Self> where T: 'a + Clone, Self: Sized + Iterator<Item = &'a T>
    let a = [1, 2, 3];
    let v_cloned: Vec<_> = a.iter().cloned().collect();
    // cloned is the same as .map(|&x| x), for integers
    let v_map: Vec<_> = a.iter().map(|&x| x).collect();
    assert_eq!(v_cloned, vec![1, 2, 3]);
    assert_eq!(v_map, vec![1, 2, 3]);

// 循环返回迭代器的元素
fn cycle(self) -> Cycle<Self> where Self: Sized + Clone { ... }
    let a = [1, 2, 3];
    let mut it = a.iter().cycle();
    assert_eq!(it.next(), Some(&1));
    assert_eq!(it.next(), Some(&2));
    assert_eq!(it.next(), Some(&3));
    assert_eq!(it.next(), Some(&1));
    assert_eq!(it.next(), Some(&2));
    assert_eq!(it.next(), Some(&3));
    assert_eq!(it.next(), Some(&1));

// 返回一个迭代器,每次迭代返回 N 个元素的数组。
fn array_chunks<const N: usize>(self) -> ArrayChunks<Self, N> where Self: Sized

// 返回元素的 sum,可能会 panic。Option/Result 也实现了 Sum
fn sum<S>(self) -> S where Self: Sized, S: Sum<Self::Item>
    let a = [1, 2, 3];
    let sum: i32 = a.iter().sum();
    assert_eq!(sum, 6);

// 返回元素的乘积
fn product<P>(self) -> P where Self: Sized, P: Product<Self::Item>
    fn factorial(n: u32) -> u32 {
        (1..=n).product()
    }
    assert_eq!(factorial(0), 1);
    assert_eq!(factorial(1), 1);
    assert_eq!(factorial(5), 120);

// 比较两个迭代的各元素,元素必须实现 Ord trait(所以不能比较 float 值)
fn cmp<I>(self, other: I) -> Ordering where I: IntoIterator<Item = Self::Item>, Self::Item: Ord, Self: Sized
use std::cmp::Ordering;
    assert_eq!([1].iter().cmp([1].iter()), Ordering::Equal);
    assert_eq!([1].iter().cmp([1, 2].iter()), Ordering::Less);
    assert_eq!([1, 2].iter().cmp([1].iter()), Ordering::Greater);

// 使用指定的 cmp 闭包函数来比较两个迭代器的元素
fn cmp_by<I, F>(self, other: I, cmp: F) -> Ordering where Self: Sized, I: IntoIterator, F: FnMut(Self::Item, <I as IntoIterator>::Item) -> Ordering
    #![feature(iter_order_by)]
    use std::cmp::Ordering;
    let xs = [1, 2, 3, 4];
    let ys = [1, 4, 9, 16];
    assert_eq!(xs.iter().cmp_by(&ys, |&x, &y| x.cmp(&y)), Ordering::Less);
    assert_eq!(xs.iter().cmp_by(&ys, |&x, &y| (x * x).cmp(&y)), Ordering::Equal);
    assert_eq!(xs.iter().cmp_by(&ys, |&x, &y| (2 * x).cmp(&y)), Ordering::Greater);

// 与 cmp 相比,partial_cmp可以比较实现 PartialOrd trait 的值,如 float64
fn partial_cmp<I>(self, other: I) -> Option<Ordering> where I: IntoIterator, Self::Item: PartialOrd<<I as IntoIterator>::Item>, Self: Sized
fn partial_cmp_by<I, F>(self, other: I, partial_cmp: F) -> Option<Ordering> where Self: Sized, I: IntoIterator, F: FnMut(Self::Item, <I as IntoIterator>::Item) -> Option<Ordering>

// 比较两个迭代器的元素,返回 ture/false
fn eq<I>(self, other: I) -> bool where I: IntoIterator, Self::Item: PartialEq<<I as IntoIterator>::Item>, Self: Sized { ... }
fn eq_by<I, F>(self, other: I, eq: F) -> bool where Self: Sized, I: IntoIterator, F: FnMut(Self::Item, <I as IntoIterator>::Item) -> bool { ... }
fn ne<I>(self, other: I) -> bool where I: IntoIterator, Self::Item: PartialEq<<I as IntoIterator>::Item>, Self: Sized { ... }
fn lt<I>(self, other: I) -> bool where I: IntoIterator, Self::Item: PartialOrd<<I as IntoIterator>::Item>, Self: Sized { ... }
fn le<I>(self, other: I) -> bool where I: IntoIterator, Self::Item: PartialOrd<<I as IntoIterator>::Item>, Self: Sized { ... }
fn gt<I>(self, other: I) -> bool where I: IntoIterator, Self::Item: PartialOrd<<I as IntoIterator>::Item>, Self: Sized { ... }
fn ge<I>(self, other: I) -> bool where I: IntoIterator, Self::Item: PartialOrd<<I as IntoIterator>::Item>, Self: Sized { ... }

// 判断迭代器的元素是否已排序
fn is_sorted(self) -> bool where Self: Sized, Self::Item: PartialOrd
fn is_sorted_by<F>(self, compare: F) -> bool where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> bool
fn is_sorted_by_key<F, K>(self, f: F) -> bool where Self: Sized, F: FnMut(Self::Item) -> K, K: PartialOrd

2 FromIterator
#

从输入的迭代器 iter 创建一个 Self 对象(取决于实现该 Fromiterator 的对象类型), 输入的 iter 是IntoIterator 类型,所以会转移 iter 对象的所有权。

迭代器的泛型方法 collect<T>() 会自动调用 T::from_iter(self) 方法来生成 T 对象。

pub trait FromIterator<A>: Sized {
    // Required method
    fn from_iter<T>(iter: T) -> Self
       where T: IntoIterator<Item = A>;
}

// 示例
let five_fives = std::iter::repeat(5).take(5);
let v = Vec::from_iter(five_fives);
assert_eq!(v, vec![5, 5, 5, 5, 5]);

// collect() 函数默认自动使用 FromIterator<A> trait
let five_fives = std::iter::repeat(5).take(5);
// 等效于:Vec<i32>::from_iter(five_fives)
let v: Vec<i32> = five_fives.collect();
assert_eq!(v, vec![5, 5, 5, 5, 5]);

实现 FromIterator<T> 的类型:

  • impl<K, V> FromIterator<(K, V)> for BTreeMap<K, V>
  • impl<T> FromIterator<T> for BTreeSet<T> where T: Ord,
  • impl<T> FromIterator<T> for Vec<T>
impl FromIterator<char> for String
impl FromIterator<()> for ()

use std::io::*;
let data = vec![1, 2, 3, 4, 5];
let res: Result<()> = data.iter()
    .map(|x| writeln!(stdout(), "{x}"))
    .collect();
assert!(res.is_ok());

impl FromIterator<Box<str>> for String
impl FromIterator<OsString> for OsString
impl FromIterator<String> for String
impl<'a> FromIterator<&'a char> for String
impl<'a> FromIterator<&'a str> for String
impl<'a> FromIterator<&'a OsStr> for OsString
impl<'a> FromIterator<Cow<'a, str>> for String
impl<'a> FromIterator<Cow<'a, OsStr>> for OsString
impl<'a> FromIterator<char> for Cow<'a, str>
impl<'a> FromIterator<String> for Cow<'a, str>
impl<'a, 'b> FromIterator<&'b str> for Cow<'a, str>
impl<'a, T> FromIterator<T> for Cow<'a, [T]> where T: Clone
impl<A, E, V> FromIterator<Result<A, E>> for Result<V, E> where V: FromIterator<A>
impl<A, V> FromIterator<Option<A>> for Option<V> where V: FromIterator<A>
impl<I> FromIterator<I> for Box<[I]>
impl<K, V> FromIterator<(K, V)> for BTreeMap<K, V> where K: Ord
impl<K, V, S> FromIterator<(K, V)> for HashMap<K, V, S> where K: Eq + Hash, S: BuildHasher + Default
impl<P: AsRef<Path>> FromIterator<P> for PathBuf
impl<T> FromIterator<T> for BTreeSet<T> where T: Ord
impl<T> FromIterator<T> for BinaryHeap<T> where T: Ord
impl<T> FromIterator<T> for LinkedList<T>
impl<T> FromIterator<T> for VecDeque<T>
impl<T> FromIterator<T> for Rc<[T]>
impl<T> FromIterator<T> for Arc<[T]>
impl<T> FromIterator<T> for Vec<T>
impl<T, S> FromIterator<T> for HashSet<T,S> where T: Eq + Hash, S: BuildHasher + Default
impl FromIterator<TokenStream> for TokenStream
impl FromIterator<TokenTree> for TokenStream
rust-lang - 这篇文章属于一个选集。
§ 13: 本文

相关文章

不安全:unsafe
··824 字
Rust
Rust
借用:refer/borrow
··3127 字
Rust
Rust 引用类型和借用
函数、方法和闭包:function/method/closure
··7032 字
Rust
Rust 函数、方法和闭包
包和模块:package/crate/module
··2066 字
Rust
Rust 项目的包和模块组织结构