Можно ли собрать итератор, чтобы заполнить коллекцию задом наперед? - PullRequest
1 голос
/ 19 июня 2019

Возможно ли собрать итератор так, чтобы он заполнял коллекцию в обратном направлении, например, используя push_front в VecDeque?

Можно собрать в Vec и затем переверните его, но, похоже, в этом нет необходимости, если структуры данных явно поддерживают эту возможность.Я хотел бы избежать написания явного цикла for, если это возможно.

Ответы [ 2 ]

2 голосов
/ 20 июня 2019

Да, это возможно:

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 цикла

Кто-то должен написать этот код.

0 голосов
/ 19 июня 2019

Можно ли собрать итератор так, чтобы он заполнял коллекцию в обратном направлении, например, используя 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

Детская площадка

...