Is it possible to collect an iterator such that it populates a collection backwards, such as using push_front
in a VecDeque
?
It's possible to collect into a Vec
and then reverse it, but it seems like it should be unnecessary with data structures explicitly supporting this capability. I'd like to avoid writing an explicit for
loop if possible.
Yes, it's possible:
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]);
}
You just need a bit of glue code:
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;
}
And implement it efficiently for various types:
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
}
}
I'd like to avoid writing an explicit for
loop
Someone has to write that code.
Is it possible to collect an iterator such that it populates a collection backwards, such as using push_front
in a VecDeque
?
Yes it is. You can iterate over your iterator with for_each
and populate your VecDeque
like this:
let mut my_deque: VecDeque<i32> = VecDeque::new();
(1..4).for_each(|x| my_deque.push_front(x));
You can reverse your iterator with the rev
method. After that, you can call for_each
to iterate it in the reverse order or you can collect it to a Vec
directly since it is already reversed.
fn main() {
let my_iterator = vec![1, 2, 3].into_iter();
let reversed_iterator = my_iterator.rev();
reversed_iterator.for_each(|x| print!("{}", x));
}
Or more idiomatically you can directly reverse it in your for
loop:
for i in (1..4).rev() {
print!("{}", i);
}
Your output will be:
321
Playground