向前和向后迭代

时间:2016-07-06 15:22:47

标签: list iterator rust

我们有一个双结尾的结构列表,例如LinkedList

我需要在元素中向前和向后迭代(例如,向前4次,然后向后2次,然后向前5次)。

在C ++中它将是:

iter++; iter++; ... iter--; ...

在Rust中,我只看到.next().rev()这是不方便的(因为经过几次迭代后我已经不知道我在哪个方向上反转了迭代)。

2 个答案:

答案 0 :(得分:4)

Iterator类似于C ++的ForwardIterator。你想要的是BidirectionalIterator,但由于类型系统的限制,Rust没有提供类似的特性。

正如Matthieu M在注释中所说,定义迭代器的方式允许保留对生成元素的引用。如果迭代器产生可变引用,这就是一个问题,因为向前和向后移动将允许对同一元素进行多次可变引用。解决此问题的一种方法是将生成元素的生命周期与&mut self联系起来,因此调用next(或prev)会借用self,但那里无法以通用方式执行此操作(有RFC来添加此类功能)。

查看Iterator特质定义:

pub trait Iterator {
    type Item;
    fn next<'a>(&'a mut self) -> Option<Self::Item>;
    // ...
}

我们可以看到Self::Item的生命周期与'a无关。解决问题的必要条件是:

pub trait Iterator {
    type Item<'a>; // hypothetical syntax
    fn next<'a>(&'a mut self) -> Option<Self::Item<'a>>;
    // ...
}

但尚不支持。

也就是说,一种选择是使用使用特定迭代器的外部包(即不实现特征)。 linked_list包提供了一个带Cursor的链表实现,允许向前和向后迭代:

use linked_list::LinkedList;
use std::iter::FromIterator;

fn main() {
    // LinkedList::cursor takes &mut self, so lst must be mutable
    let mut lst = LinkedList::from_iter(0..10);
    let mut c = lst.cursor();

    c.next();
    c.next();
    c.next();
    c.prev();

    assert_eq!(1, *c.prev().unwrap());
}

Cursor不允许保留对所产生元素的引用。文档说:

  

Cursor就像一个迭代器,除了它可以自由地来回搜索,并且可以在迭代期间安全地改变列表。这是因为其产生的引用的生命周期与其自身的生命周期有关,而不仅仅与基础列表有关。这意味着游标不能同时产生多个元素。

以下示例:

let a = c.next();
let b = c.next();

生成此错误:

error: cannot borrow `c` as mutable more than once at a time [E0499]
    let b = c.next();

这是因为next(和prev)借鉴self,即:

fn next<'a>(&'a mut self) -> Option<&'a mut T>

答案 1 :(得分:3)

您需要实现自己的迭代器才能执行此操作。以下是Vec s的示例实现:

pub trait ForwardBackwardIterator : Iterator {
    fn prev(&mut self) -> Option<Self::Item>;
}

pub struct VectorForwardBackwardIterator<'a, Item> where Item : 'a {
    index: Option<usize>,
    vector: &'a Vec<Item>,
}

impl<'a, Item> VectorForwardBackwardIterator<'a, Item> {
    fn new(vector: &'a Vec<Item>) -> VectorForwardBackwardIterator<'a, Item> {
        VectorForwardBackwardIterator { index: None, vector: vector }
    }
}

impl<'a, Item> Iterator for VectorForwardBackwardIterator<'a, Item> {
    type Item = &'a Item;

    fn next(&mut self) -> Option<&'a Item> {
        let index = 
            match self.index {
                Some(i) => i + 1,
                None => 0
            };

        self.index = Some(index);
        self.vector.get(index)
    }
}

impl<'a, Item> ForwardBackwardIterator for VectorForwardBackwardIterator<'a, Item> {
    fn prev(&mut self) -> Option<&'a Item> {
        let index = 
            match self.index {
                Some(0) | None => return None,
                Some(i) => i - 1
            };

        self.index = Some(index);
        self.vector.get(index)
    }
}

fn main() {
    let v = vec![0, 1, 2, 3, 4, 5];
    let mut iterator = VectorForwardBackwardIterator::new(&v);

    println!("{:?}", iterator.next());
    println!("{:?}", iterator.next());
    println!("{:?}", iterator.next());
    println!("{:?}", iterator.prev());
    println!("{:?}", iterator.prev());
}

打印出来

Some(0)
Some(1)
Some(2)
Some(1)
Some(0)