【问题标题】:Chain Vector and IntoIterator element in RustRust 中的链式向量和 IntoIterator 元素
【发布时间】:2019-10-13 21:05:01
【问题描述】:

我想在 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】:

    这里有一些提示:

    • 您已经创建了三个独立的向量(一个明确的,两个使用 collect),而实际上您只需要一个。
    • 您可以使用std::iter::once 迭代器为开始和结束整数生成迭代器
    • 无需收集中间范围。 intermediate 参数实现了IntoIterator,因此您可以将其直接提供给chain。因此,您可以将开始、中间和结束链接在一起。
    • 无需在函数末尾使用“return”关键字 - 函数的结果是其中最后一个表达式的值(只要末尾没有分号)。

    应用这些提示,您的函数将如下所示:

    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()
    }
    

    还有一点需要注意,回答 cmets 的问题:

    为什么要这样做:a1.iter().chain(intermediate) 使用链方法会出错

    调用Vec::iter() 会返回一个迭代器,该迭代器会将references 返回到向量中的值。这是有道理的:调用iter() 不会消耗向量,并且它的内容保持不变:如果需要,您可以对其进行多次迭代。

    另一方面,从IntoIterator trait 调用into_iter() 会返回一个返回的迭代器。这也是有道理的:into_iter() 确实消耗了您调用它的对象,因此迭代器随后获得了该对象先前拥有的项目的所有权。

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

    let mut iter : Vec<u32> = a1.into_iter().chain(intermediate).collect();
    

    【讨论】:

    • 非常感谢,我得到了您的积分,您建议的解决方案似乎比我的代码最佳。是否也可以解释为什么要尝试这个: a1.iter().chain(intermediate) 给出了链方法的错误:类型不匹配解析...?因为我认为这应该像 once(start) 一样提供迭代器,不是吗?
    • @AnaKhorguani 答案已更新以解决您的问题。
    • 啊,我明白了。非常感谢:)
    猜你喜欢
    • 1970-01-01
    • 2023-01-09
    • 1970-01-01
    • 2017-04-07
    • 2019-07-30
    • 1970-01-01
    • 2022-11-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多