如何使用trait实现迭代器

4

我有一个称为Library的结构体,其中包含了一个字符串向量(titles)。我已经为此实现了一个迭代器。以下是我的代码:

#[derive(Debug, Clone)]
struct Library {
    books: Vec<String>
}

impl Iterator for Library {
    fn next(&mut self) -> Option<Self::Item> {
        ...
    }
}

现在,我正在尝试使用trait来实现迭代器,代码如下:

fn foo(x: Vec<u32>) -> impl Iterator<Item=u32> {
    //Unsure if correct method
    fn next() -> Option<...> {
       x.into_iter()....

    }
}

但我不确定在这种情况下该怎么做。我只需要重新定义一个next()方法吗?根据其他资源的说法,似乎并非如此。为什么呢?一个被返回的迭代器不应该有一个next()方法吗?

通过这种方式实现迭代器的一般方法是什么?


3
这个回答解决了你的问题吗?为包含可迭代字段的结构体实现Iterator trait - Locke
1个回答

7
您不需要直接在Library上实现特性。该库不是迭代器,但可以由迭代器迭代。
相反,只需声明一个返回迭代器的方法即可,您可以直接从向量返回迭代器,无需自定义迭代器实现。例如:
impl Library {
    fn iter(&self) -> impl Iterator<Item=&String> {
        self.books.iter()
    }
}

对于您的第二种情况,您可以使用into_iter()将向量转换为迭代器,该方法由IntoIterator trait提供:

fn foo(x: Vec<u32>) -> impl Iterator<Item=u32> {
    x.into_iter()
}

好的,我理解.into_iter()。如果我的类型更复杂呢?比如fn foo<A>(x: Vec<A>) -> impl Iterator<Item = (u32,A)>?我希望迭代器遍历x中的每个元素,并根据某些条件返回(0,A)或(1,A)。 - Darrel Gulseth
同样地,如果我有一个 fn foo(x: Vec<u32>) -> impl Iterator<Item = (u32, u32)>,会怎么样呢? - Darrel Gulseth
@DarrelGulseth 这就是标准迭代器工具(例如 .map())派上用场的地方。因此,您可以执行 x.into_iter().map(|v| /* some expression here */). - cdhowie
@DarrelGulseth 这完全取决于您想如何迭代。如果您想将嵌套向量展平为一个 u32 迭代器,那么只需执行 x.into_iter().flatten() 即可。 - cdhowie
这提供了很多清晰度!谢谢。 - Darrel Gulseth
1
@DarrelGulseth 没问题。Iterator特质提供了数十种这样的实用工具。使用它们,您可以执行几乎任何您能想到的序列操作。除非您正在实现类似分页API客户端或从头开始实现自己的数据结构之类的东西,否则很少需要实现自己的迭代器。 - cdhowie

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接