我们有一个双结尾的结构列表,例如LinkedList
。
我需要在元素中向前和向后迭代(例如,向前4次,然后向后2次,然后向前5次)。
在C ++中它将是:
iter++; iter++; ... iter--; ...
在Rust中,我只看到.next()
和.rev()
这是不方便的(因为经过几次迭代后我已经不知道我在哪个方向上反转了迭代)。
答案 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)