【问题标题】:Is it possible to collect an iterator to populate a collection backwards?是否可以收集一个迭代器来向后填充一个集合?
【发布时间】:2019-11-02 15:44:03
【问题描述】:

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

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

【问题讨论】:

标签: collections rust iterator


【解决方案1】:

是否可以收集一个迭代器,使其向后填充一个集合,例如在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

Playground

【讨论】:

  • 可以调用 for_each 进行迭代 — 或者,更习惯地说,在 for 循环中使用它。
  • 可能值得直接从 OP 解决这一点:向后填充集合,例如在VecDeque 中使用push_front
  • 对,for 循环。正如我所说,我想避免这种情况。
  • @Listerone push_front 是您想要应用于迭代器的每个元素的副作用。必须有一个循环调用它,无论是for_each() 还是for。对于学习像 Rust 或 F# 这样的混合范式语言的人来说,循环本质上是一件坏事,这是一个常见的误解。如果有像map 这样的函数可以更好地表达程序的语义,那么你应该使用它;但如果你真正要做的是“对集合中的每个元素执行副作用”,那么循环就没有问题。
【解决方案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 循环

必须有人编写该代码。

【讨论】:

    猜你喜欢
    • 2019-07-31
    • 1970-01-01
    • 2011-07-15
    • 1970-01-01
    • 2015-02-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多