如何编写一个返回对自身引用的迭代器?

如何编写一个返回对自身引用的迭代器?

我无法表达Iterator实现的返回值的生命周期。如何在不更改迭代器的返回值的情况下编译此代码?我希望它返回一个引用的向量。

很明显,我没有正确使用生命周期参数,但在尝试了我放弃的各种方法之后,我不知道如何处理它。

use std::iter::Iterator;struct PermutationIterator<T> {
    vs: Vec<Vec<T>>,
    is: Vec<usize>,}impl<T> PermutationIterator<T> {
    fn new() -> PermutationIterator<T> {
        PermutationIterator {
            vs: vec![],
            is: vec![],
        }
    }

    fn add(&mut self, v: Vec<T>) {
        self.vs.push(v);
        self.is.push(0);
    }}impl<T> Iterator for PermutationIterator<T> {
    type Item = Vec<&'a T>;
    fn next(&mut self) -> Option<Vec<&T>> {
        'outer: loop {
            for i in 0..self.vs.len() {
                if self.is[i] >= self.vs[i].len() {
                    if i == 0 {
                        return None; // we are done
                    }
                    self.is[i] = 0;
                    self.is[i - 1] += 1;
                    continue 'outer;
                }
            }

            let mut result = vec![];

            for i in 0..self.vs.len() {
                let index = self.is[i];
                result.push(self.vs[i].get(index).unwrap());
            }

            *self.is.last_mut().unwrap() += 1;

            return Some(result);
        }
    }}fn main() {
    let v1: Vec<_> = (1..3).collect();
    let v2: Vec<_> = (3..5).collect();
    let v3: Vec<_> = (1..6).collect();

    let mut i = PermutationIterator::new();
    i.add(v1);
    i.add(v2);
    i.add(v3);

    loop {
        match i.next() {
            Some(v) => {
                println!("{:?}", v);
            }
            None => {
                break;
            }
        }
    }}

游乐场链接

error[E0261]: use of undeclared lifetime name `'a`
  --> src/main.rs:23:22
   |
23 |     type Item = Vec<&'a T>;
   |                      ^^ undeclared lifetime



慕沐林林
浏览 655回答 3
3回答

慕村225694

据我所知,你想要迭代器将引用向量返回给自己,对吧?不幸的是,在Rust中是不可能的。这是减少的Iterator特性:trait&nbsp;Iterator&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;type&nbsp;Item; &nbsp;&nbsp;&nbsp;&nbsp;fn&nbsp;next(&mut&nbsp;self)&nbsp;->&nbsp;Option<Item>;}请注意,和之间没有生命周期连接。这意味着该方法不能将引用返回到迭代器本身。你只是无法表达返回引用的生命周期。这基本上是你找不到指定正确生命周期的方法的原因 - 它看起来像这样:&mut selfOption<Item>next()fn&nbsp;next<'a>(&'a&nbsp;mut&nbsp;self)&nbsp;->&nbsp;Option<Vec<&'a&nbsp;T>>除了这不是一个有效next()的Iterator特质方法。这些迭代器(可以将引用返回到它们自己的迭代器)称为流迭代器。如果你愿意,你可以在这里,这里和这里找到更多。更新。但是,您可以从迭代器返回对其他结构的引用 - 这就是大多数集合迭代器的工作方式。它可能看起来像这样:pub&nbsp;struct&nbsp;PermutationIterator<'a,&nbsp;T>&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;vs:&nbsp;&'a&nbsp;[Vec<T>], &nbsp;&nbsp;&nbsp;&nbsp;is:&nbsp;Vec<usize>}impl<'a,&nbsp;T>&nbsp;Iterator&nbsp;for&nbsp;PermutationIterator<'a,&nbsp;T>&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;type&nbsp;Item&nbsp;=&nbsp;Vec<&'a&nbsp;T>; &nbsp;&nbsp;&nbsp;&nbsp;fn&nbsp;next(&mut&nbsp;self)&nbsp;->&nbsp;Option<Vec<&'a&nbsp;T>>&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;... &nbsp;&nbsp;&nbsp;&nbsp;}}注意'a现在如何在impl块上声明生命周期。可以这样做(事实上是必需的)因为你需要在结构上指定生命周期参数。然后你可以使用相同的'ain&nbsp;Item和next()return类型。同样,这就是大多数集合迭代器的工作方式。

慕无忌1623718

它可以从其他东西中产生借来的价值。这是与实现Vec和Iter:在Vec拥有值,并且在Iter刚能中产生的引用的包装Vec。这是一个实现您想要的设计。迭代器就像Vec和Iter,和实际拥有值的其他容器一样。use&nbsp;std::iter::Iterator;struct&nbsp;PermutationIterator<'a,&nbsp;T:&nbsp;'a>&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;vs&nbsp;:&nbsp;Vec<&'a&nbsp;[T]>, &nbsp;&nbsp;&nbsp;&nbsp;is&nbsp;:&nbsp;Vec<usize>}impl<'a,&nbsp;T>&nbsp;PermutationIterator<'a,&nbsp;T>&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;fn&nbsp;new()&nbsp;->&nbsp;PermutationIterator<'a,&nbsp;T>&nbsp;{&nbsp;...&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;fn&nbsp;add(&mut&nbsp;self,&nbsp;v&nbsp;:&nbsp;&'a&nbsp;[T])&nbsp;{&nbsp;...&nbsp;}}impl<'a,&nbsp;T>&nbsp;Iterator&nbsp;for&nbsp;PermutationIterator<'a,&nbsp;T>&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;type&nbsp;Item&nbsp;=&nbsp;Vec<&'a&nbsp;T>; &nbsp;&nbsp;&nbsp;&nbsp;fn&nbsp;next(&mut&nbsp;self)&nbsp;->&nbsp;Option<Vec<&'a&nbsp;T>>&nbsp;{&nbsp;...&nbsp;}}fn&nbsp;main()&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;let&nbsp;v1&nbsp;:&nbsp;Vec<i32>&nbsp;=&nbsp;(1..3).collect(); &nbsp;&nbsp;&nbsp;&nbsp;let&nbsp;v2&nbsp;:&nbsp;Vec<i32>&nbsp;=&nbsp;(3..5).collect(); &nbsp;&nbsp;&nbsp;&nbsp;let&nbsp;v3&nbsp;:&nbsp;Vec<i32>&nbsp;=&nbsp;(1..6).collect(); &nbsp;&nbsp;&nbsp;&nbsp;let&nbsp;mut&nbsp;i&nbsp;=&nbsp;PermutationIterator::new(); &nbsp;&nbsp;&nbsp;&nbsp;i.add(&v1); &nbsp;&nbsp;&nbsp;&nbsp;i.add(&v2); &nbsp;&nbsp;&nbsp;&nbsp;i.add(&v3); &nbsp;&nbsp;&nbsp;&nbsp;loop&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;match&nbsp;i.next()&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Some(v)&nbsp;=>&nbsp;{&nbsp;println!("{:?}",&nbsp;v);&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;None&nbsp;=>&nbsp;{break;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;}}(操场)与您的初始问题无关。如果这只是我,我会确保所有借来的载体都是一次性的。我们的想法是删除重复调用add并直接传递构造中所有借用的向量:use&nbsp;std::iter::{Iterator,&nbsp;repeat};struct&nbsp;PermutationIterator<'a,&nbsp;T:&nbsp;'a>&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;...}impl<'a,&nbsp;T>&nbsp;PermutationIterator<'a,&nbsp;T>&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;fn&nbsp;new(vs:&nbsp;Vec<&'a&nbsp;[T]>)&nbsp;->&nbsp;PermutationIterator<'a,&nbsp;T>&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;let&nbsp;n&nbsp;=&nbsp;vs.len(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PermutationIterator&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;vs:&nbsp;vs, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;is:&nbsp;repeat(0).take(n).collect(), &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;}}impl<'a,&nbsp;T>&nbsp;Iterator&nbsp;for&nbsp;PermutationIterator<'a,&nbsp;T>&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;...}fn&nbsp;main()&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;let&nbsp;v1&nbsp;:&nbsp;Vec<i32>&nbsp;=&nbsp;(1..3).collect(); &nbsp;&nbsp;&nbsp;&nbsp;let&nbsp;v2&nbsp;:&nbsp;Vec<i32>&nbsp;=&nbsp;(3..5).collect(); &nbsp;&nbsp;&nbsp;&nbsp;let&nbsp;v3&nbsp;:&nbsp;Vec<i32>&nbsp;=&nbsp;(1..6).collect(); &nbsp;&nbsp;&nbsp;&nbsp;let&nbsp;vall:&nbsp;Vec<&[i32]>&nbsp;=&nbsp;vec![&v1,&nbsp;&v2,&nbsp;&v3]; &nbsp;&nbsp;&nbsp;&nbsp;let&nbsp;mut&nbsp;i&nbsp;=&nbsp;PermutationIterator::new(vall);}(操场)(编辑:将迭代器设计改为采用Vec<&'a [T]>而不是a&nbsp;Vec<Vec<&'a T>>。使用ref容器比构建refs容器更容易。)

慕标5832272

正如其他答案中所提到的,这被称为流式迭代器,它需要Rust的不同保证Iterator。提供此类功能的一个箱子恰当地称为流式迭代器,它提供了StreamingIterator特性。以下是实现特征的一个示例:extern&nbsp;crate&nbsp;streaming_iterator;use&nbsp;streaming_iterator::StreamingIterator;struct&nbsp;Demonstration&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;scores:&nbsp;Vec<i32>, &nbsp;&nbsp;&nbsp;&nbsp;position:&nbsp;usize,}//&nbsp;Since&nbsp;`StreamingIterator`&nbsp;requires&nbsp;that&nbsp;we&nbsp;be&nbsp;able&nbsp;to&nbsp;call//&nbsp;`advance`&nbsp;before&nbsp;`get`,&nbsp;we&nbsp;have&nbsp;to&nbsp;start&nbsp;"before"&nbsp;the&nbsp;first//&nbsp;element.&nbsp;We&nbsp;assume&nbsp;that&nbsp;there&nbsp;will&nbsp;never&nbsp;be&nbsp;the&nbsp;maximum&nbsp;number&nbsp;of//&nbsp;entries&nbsp;in&nbsp;the&nbsp;`Vec`,&nbsp;so&nbsp;we&nbsp;use&nbsp;`usize::MAX`&nbsp;as&nbsp;our&nbsp;sentinel&nbsp;value.impl&nbsp;Demonstration&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;fn&nbsp;new()&nbsp;->&nbsp;Self&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Demonstration&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;scores:&nbsp;vec![1,&nbsp;2,&nbsp;3], &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;position:&nbsp;std::usize::MAX, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;fn&nbsp;reset(&mut&nbsp;self)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.position&nbsp;=&nbsp;std::usize::MAX; &nbsp;&nbsp;&nbsp;&nbsp;}}impl&nbsp;StreamingIterator&nbsp;for&nbsp;Demonstration&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;type&nbsp;Item&nbsp;=&nbsp;i32; &nbsp;&nbsp;&nbsp;&nbsp;fn&nbsp;advance(&mut&nbsp;self)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.position&nbsp;=&nbsp;self.position.wrapping_add(1); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;fn&nbsp;get(&self)&nbsp;->&nbsp;Option<&Self::Item>&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.scores.get(self.position) &nbsp;&nbsp;&nbsp;&nbsp;}}fn&nbsp;main()&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;let&nbsp;mut&nbsp;example&nbsp;=&nbsp;Demonstration::new(); &nbsp;&nbsp;&nbsp;&nbsp;loop&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;example.advance(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;match&nbsp;example.get()&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Some(v)&nbsp;=>&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;println!("v:&nbsp;{}",&nbsp;v); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;None&nbsp;=>&nbsp;break, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;example.reset(); &nbsp;&nbsp;&nbsp;&nbsp;loop&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;example.advance(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;match&nbsp;example.get()&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Some(v)&nbsp;=>&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;println!("v:&nbsp;{}",&nbsp;v); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;None&nbsp;=>&nbsp;break, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;}}不幸的是,在实现RFC 1598的通用关联类型(GAT)之前,流式迭代器将受到限制。
打开App,查看更多内容
随时随地看视频慕课网APP