【发布时间】:2019-11-02 15:44:03
【问题描述】:
是否可以收集一个迭代器,使其向后填充一个集合,例如在VecDeque 中使用push_front?
可以收集到Vec 然后将其反转,但是对于明确支持此功能的数据结构似乎没有必要。如果可能,我想避免编写显式的 for 循环。
【问题讨论】:
-
有了
ExactSizeIterator你应该可以做到
标签: collections rust iterator
是否可以收集一个迭代器,使其向后填充一个集合,例如在VecDeque 中使用push_front?
可以收集到Vec 然后将其反转,但是对于明确支持此功能的数据结构似乎没有必要。如果可能,我想避免编写显式的 for 循环。
【问题讨论】:
ExactSizeIterator 你应该可以做到
标签: collections rust iterator
是否可以收集一个迭代器,使其向后填充一个集合,例如在
VecDeque中使用push_front?
是的。您可以使用 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
【讨论】:
for_each 进行迭代 — 或者,更习惯地说,在 for 循环中使用它。
VecDeque 中使用push_front。
push_front 是您想要应用于迭代器的每个元素的副作用。必须有一个循环调用它,无论是for_each() 还是for。对于学习像 Rust 或 F# 这样的混合范式语言的人来说,循环本质上是一件坏事,这是一个常见的误解。如果有像map 这样的函数可以更好地表达程序的语义,那么你应该使用它;但如果你真正要做的是“对集合中的每个元素执行副作用”,那么循环就没有问题。
是的,有可能:
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循环
必须有人编写该代码。
【讨论】: