【问题标题】:Pass Vec as Iterator to function将 Vec 作为迭代器传递给函数
【发布时间】:2019-11-09 11:47:30
【问题描述】:

我想做什么:

  • 我有一个结构,其中包含另一个结构的 Vec
  • 我会不时更新这个Vec
  • 我想将此Vec 作为Iterator 传递给另一个函数。

下面是一个简短的代码 sn-p,说明我想如何做事,但我无法编译我所做的任何事情:

struct Main {
    data: Vec<OtherStruct>
}

callFunctionHere(self.data.iter());

pub fn callFunctionHere<I>(data: I)
where
     I: Iterator<Item = OtherStruct>,
{
   // for i in data...
}

我可以将数据作为某种新的复制对象传递吗?

【问题讨论】:

    标签: rust


    【解决方案1】:

    您需要Iterator&lt;Item = &amp;OtherStruct&gt; 的特征绑定,因为Vec&lt;T&gt;::iter 通过引用 将迭代器返回到T。生成 T 值的迭代器必须将它们移出向量,这只有在向量本身被消耗时才是安全的,这也是 Vec&lt;T&gt;::into_iter() 所做的。

    请注意,您还需要指定引用的生命周期,与数据的生命周期相关联:

    fn some_function<'a, I>(data: I)
    where
        I: Iterator<Item = &'a Other> + 'a,
    {
        for el in data {
            println!("{:?}", el)
        }
    }
    

    完整示例in the playground

    最后,值得指出的是,一般来说,最好请求IntoIterator 绑定而不是Iterator。由于Iterator 实现了IntoIterator,因此此类函数将继续接受迭代器,但也会接受可以转换为迭代器的对象。在这种情况下,除了s.data.iter() 之外,它还将接受&amp;s.data

    【讨论】:

    • 然后我得到“这里需要显式生命周期名称”,我把 &
    • @liljan 是的,编译器无法推断引用的生命周期,因此您需要明确指定它。我现在修改了答案以显示一个示例。
    • 你应该几乎总是在IntoIterator而不是Iterator上绑定参数类型,因为它更通用;例如,在这种情况下,您也可以传递 some_function(&amp;s.data) 而无需调用 iter()
    • @trentcl 好的,谢谢。我现在修改了答案,为简单起见保持原样,但添加了一段宣传IntoIterator 的优点。
    【解决方案2】:

    我解决了这个问题:

    callFunctionHere(data.iter().map(|i| OtherStruct{
        d: i.d
    })
    ´´´
    

    【讨论】:

    • 这可能不是你想要的。如果你真的想复制结构体,只要OtherStruct 实现Clonedata.iter().cloned() 就可以完成这项工作。但是如果callFunctionHere 不需要使用OtherStructs,你应该让它接受引用并遵循user4815162342 的回答。
    猜你喜欢
    • 1970-01-01
    • 2013-12-13
    • 2013-06-03
    • 1970-01-01
    • 2014-06-26
    • 2013-09-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多