rust 向前和向后迭代

rt4zxlrg  于 2023-01-05  发布在  其他
关注(0)|答案(3)|浏览(197)

我们有一个结构体的双端列表,例如LinkedList
我需要向前和向后迭代元素(比如,向前4次,然后向后2次,再向前5次)。
在C++中,它将是:

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

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

ncgqoxb0

ncgqoxb01#

Iterator类似于C++的ForwardIterator,您想要的是BidirectionalIterator,但是Rust没有提供类似的trait,因为类型系统的限制。
正如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>>;
    // ...
}

但是这还不被支持。
也就是说,一种选择是使用一个使用特定迭代器外部crate(也就是说,不实现trait)linked_list crate为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>
pinkon5k

pinkon5k2#

你需要实现自己的迭代器来完成这个任务,下面是一个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)
w6lpcovy

w6lpcovy3#

此实现允许您使用from_iter函数从迭代器创建List,并使用into_iter函数将List转换为迭代器。IntoIter类型是使用List的迭代器,next方法以插入元素的顺序返回列表元素。

use std::mem;
use std::ptr;
use std::iter::{self, FromIterator};

struct Node<T> {
    elem: T,
    next: Option<Box<Node<T>>>,
    prev: Option<Box<Node<T>>>,
}

struct List<T> {
    head: Option<Box<Node<T>>>,
    tail: Option<Box<Node<T>>>,
}

struct Iter<'a, T> {
    head: Option<&'a Box<Node<T>>>,
    tail: Option<&'a Box<Node<T>>>,
    rev: bool,
}

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

    fn next(&mut self) -> Option<Self::Item> {
        if self.rev {
            self.tail.map(|node| {
                self.tail = node.prev.as_ref();
                &node.elem
            })
        } else {
            self.head.map(|node| {
                self.head = node.next.as_ref();
                &node.elem
            })
        }
    }
}

impl<T> List<T> {
    fn new() -> Self {
        List { head: None, tail: None }
    }

    fn iter(&self) -> Iter<T> {
        Iter {
            head: self.head.as_ref(),
            tail: self.tail.as_ref(),
            rev: false,
        }
    }

    fn iter_rev(&self) -> Iter<T> {
        Iter {
            head: self.tail.as_ref(),
            tail: self.head.as_ref(),
            rev: true,
        }
    }
}

impl<T> FromIterator<T> for List<T> {
    fn from_iter<I: IntoIterator<Item=T>>(iter: I) -> Self {
        let mut list = List::new();
        for elem in iter {
            list.push_back(elem);
        }
        list
    }
}

impl<T> IntoIterator for List<T> {
    type Item = T;
    type IntoIter = IntoIter<T>;

    fn into_iter(self) -> Self::IntoIter {
        IntoIter { list: self }
    }
}

struct IntoIter<T> {
    list: List<T>,
}

impl<T> Iterator for IntoIter<T> {
    type Item = T;

    fn next(&mut self) -> Option<Self::Item> {
        self.list.pop_front()
    }
}

相关问题