是否可以收集迭代器以向后填充集合?

时间:2019-06-19 20:37:38

标签: collections rust iterator

是否有可能收集一个迭代器,以使其向后填充集合,例如在push_front中使用VecDeque

可以收集到Vec中然后反转它,但是对于明确支持该功能的数据结构来说似乎没有必要。如果可能的话,我想避免编写显式的for循环。

2 个答案:

答案 0 :(得分:2)

是的,有可能:

use std::collections::VecDeque;

fn main() {
    let v: VecDeque<_> = (0..=2).collect_rev();
    assert_eq!(v, [2, 1, 0]);

    let v: Vec<_> = (0..=2).collect_rev();
    assert_eq!(v, [2, 1, 0]);
}

您只需要一点胶水代码:

trait CollectRev: Iterator {
    fn collect_rev<B>(self) -> B
    where
        B: FromIteratorRev<Self::Item>,
        Self: Sized,
    {
        B::from_iter_rev(self)
    }
}

impl<I: Iterator> CollectRev for I {}

trait FromIteratorRev<T> {
    fn from_iter_rev(iter: impl IntoIterator<Item = T>) -> Self;
}

并针对各种类型有效地实现它:

impl<T> FromIteratorRev<T> for VecDeque<T> {
    fn from_iter_rev(iter: impl IntoIterator<Item = T>) -> Self {
        let mut v = Self::new();
        for i in iter {
            v.push_front(i);
        }
        v
    }
}

impl<T> FromIteratorRev<T> for Vec<T> {
    fn from_iter_rev(iter: impl IntoIterator<Item = T>) -> Self {
        let mut v: Self = iter.into_iter().collect();
        v.reverse();
        v
    }
}
  

我想避免编写明确的for循环

必须要编写该代码。

答案 1 :(得分:0)

  

是否有可能收集迭代器,使其向后填充集合,例如在push_front中使用VecDeque

是的。您可以使用for_each遍历迭代器,并像这样填充VecDeque

let mut my_deque: VecDeque<i32> = VecDeque::new();
(1..4).for_each(|x| my_deque.push_front(x));

您可以使用rev方法反转迭代器。之后,您可以调用for_each以相反的顺序对其进行迭代,或者可以将其收集到Vec中,因为它已经被反向。

fn main() {
    let my_iterator = vec![1, 2, 3].into_iter();
    let reversed_iterator = my_iterator.rev();
    reversed_iterator.for_each(|x| print!("{}", x));
}

或更惯用的是,您可以在for循环中直接将其反转:

for i in (1..4).rev() {
    print!("{}", i);
}

您的输出将是:

  
321

Playground