我试图在Vec中存储一系列条目。稍后,我需要通过Vec重新处理,在每个条目中填写关于下一个条目的一些信息。最小的例子是这样的:
struct Entry {
curr: i32,
next: Option<i32>
}
struct History {
entries: Vec<Entry>
}
,其中我想将next
字段填充到下一个条目的curr
值。为了实现这一点,我想在可变迭代器上使用Itertools中的tuple_windows
函数。我希望我可以这样写一个函数:
impl History {
fn fill_next_with_itertools(&mut self) {
for (a, b) in self.entries.iter_mut().tuple_windows() {
a.next = Some(b.curr);
}
}
}
(游乐场)
但是,它拒绝编译,因为迭代器Item
的类型&mut Entry
不是tuple_windows
函数所要求的Clone
。我知道有一种方法可以使用像这样的索引来迭代列表:
fn fill_next_with_index(&mut self) {
for i in 0..(self.entries.len()-1) {
self.entries[i].next = Some(self.entries[i+1].curr);
}
}
(游乐场)
但是我觉得itertools的方法更自然和优雅。达到同样效果的最好方法是什么?
来自文档:tuple_window
克隆迭代器元素,使它们可以成为连续窗口的一部分,这使得它最适合用于引用和其他值的迭代器,这些值的复制成本很低。
这意味着如果你要用&mut
项来实现它,那么你就会有多个对同一事物的可变引用,这是未定义的行为。
如果你仍然需要共享的,可变的访问,你必须把它包装在Rc<RefCell<T>>
,Arc<Mutex<T>>
或类似的东西:
fn fill_next_with_itertools(&mut self) {
for (a, b) in self.entries.iter_mut().map(RefCell::new).map(Rc::new).tuple_windows() {
a.borrow_mut().next = Some(b.borrow().curr);
}
}