使用 Itertools 的 tuple_windows 可变地迭代迭代器

问题描述 投票:0回答:1

我正在尝试在 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的做法更加自然和优雅。达到相同效果的最佳方法是什么?

rust iterator rust-itertools
1个回答
1
投票

来自文档

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);
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.