我想在 Rust 中编写一个函数,该函数将返回由起始整数、所有中间整数和结束整数组成的向量。它应该持有的断言是这样的:
assert_eq!(intervals(0, 4, 1..4), vec![0, 1, 2, 3, 4]);
Run Code Online (Sandbox Code Playgroud)
提示是对迭代器使用链方法。函数声明是预定义的,我是用一种方式实现的,代码如下:
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;
}
Run Code Online (Sandbox Code Playgroud)
但我非常确信这并不是实现此目的的最佳方式。我确信我在中间两行做了很多不必要的事情。我尝试像这样直接使用中间体:
let mut iter: Vec<u32> = a1.iter().chain(intermediate).map(|x| *x).collect();
Run Code Online (Sandbox Code Playgroud)
但是我收到链方法的这个错误,我不知道如何解决它:
type mismatch resolving <I as std::iter::IntoIterator>::Item==&u32,
expected u32, found &u32
Run Code Online (Sandbox Code Playgroud)
我是 Rust 的超级新手,所以任何建议都有助于了解在此处使用中间参数的正确方法是什么。
这里有一些提示:
collect),而实际上您只需要一个。std::iter::once迭代器为开始和结束整数生成迭代器intermediate参数工具IntoIterator,这样你就可以直接喂它chain。因此,您可以将开始、中间和结束链接在一起。应用这些技巧,您的函数将如下所示:
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()
}
Run Code Online (Sandbox Code Playgroud)
需要注意的另一件事是,从评论中回答您的问题:
为什么要尝试这个: a1.iter().chain(intermediate) 使用链方法给出错误
调用Vec::iter()返回一个迭代器,该迭代器返回对向量中值的引用。这是有道理的:调用iter()不会消耗向量,并且其内容保持不变:如果需要,您可以多次迭代它。
另一方面,into_iter()从IntoIteratortrait调用会返回一个返回值的迭代器。这也是有道理的:into_iter()确实消耗了您正在调用它的对象,因此迭代器然后获得该对象以前拥有的项目的所有权。
尝试将两个这样的迭代器链接在一起是行不通的,因为它们每个迭代器都在迭代不同的类型。一种解决方案是也消耗 a1,如下所示:
let mut iter : Vec<u32> = a1.into_iter().chain(intermediate).collect();
Run Code Online (Sandbox Code Playgroud)