我正在尝试在 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
不是Clone
函数所需的tuple_windows
。我知道有一种方法可以使用这样的索引来迭代列表:
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);
}
}