Rust中的链向量和IntoIterator元素

问题描述 投票:0回答:1

我想在Rust中编写一个函数,该函数将返回由以下各项组成的向量:起始整数,然后是所有中间整数,然后是结束整数。它应该持有的断言是:

assert_eq!(intervals(0, 4, 1..4), vec![0, 1, 2, 3, 4]);

提示是使用迭代器的链方法。函数声明是预定义的,我以一种方式实现了它,它是以下代码:

pub fn intervals< I>(start: u32, end: u32, intermediate: I) -> Vec<u32>
where
    I: IntoIterator<Item = u32>,
{
    let mut a1 = vec![];
    a1.push(start);

    let inter: Vec<u32> = intermediate.into_iter().collect();
    let mut iter : Vec<u32> = a1.iter().chain(inter.iter()).map(|x| *x).collect();

    iter.push(end);
    return iter;
}

但是我非常相信这不是实现此目的的最佳方法。我确定我在中间两行中做了很多不必要的事情。我试图像这样直接使用中间体:

let mut iter: Vec<u32> = a1.iter().chain(intermediate).map(|x| *x).collect();

但是我在使用链方法时遇到此错误,我不知道如何解决:

type mismatch resolving <I as std::iter::IntoIterator>::Item==&u32, 
expected u32, found &u32

我在Rust中是超级新手,因此任何建议都将有助于理解此处使用中间参数的正确方法。

rust iterator
1个回答
3
投票

以下是一些提示:

  • 实际上创建了三个单独的向量(一个显式,两个使用collect时,实际上只需要一个。
  • 您可以使用std::iter::once迭代器为起始整数和结束整数生成迭代器
  • 无需收集中间范围。 std::iter::once参数实现intermediate,因此您可以将其直接输入IntoIterator。因此,您可以将开始,中间和结束链接在一起。
  • 不需要在函数的末尾使用'return'关键字-函数的结果是其中的最后一个表达式的值(只要末尾没有分号即可。]

应用这些技巧,您的功能将如下所示:

chain

另外要注意的一件事,是从评论中回答您的问题:

为什么要这样做:a1.iter()。chain(intermediate)给出链方法错误

调用chain返回一个迭代器,该迭代器将references返回到向量中的值。这是有道理的:调用use std::iter::once; pub fn intervals< I>(start: u32, end: u32, intermediate: I) -> Vec<u32> where I: IntoIterator<Item = u32>, { once(start).chain(intermediate).chain(once(end)).collect() } 不会消耗向量,并且向量的内容保持不变:如果需要,您可以对其进行多次迭代。

另一方面,从Vec::iter()特征调用iter()将返回返回values的迭代器。这也很有意义:into_iter()确实消耗了您正在调用它的对象,因此迭代器将对该对象先前拥有的项目拥有所有权。

尝试将两个这样的迭代器链接在一起是行不通的,因为它们每个都在迭代不同的类型。一种解决方案是也消耗a1,如下所示:

IntoIterator
© www.soinside.com 2019 - 2024. All rights reserved.