如何在 Rust 中实现带有 HashMap 突变的嵌套循环?

Pas*_*ito 5 ownership rust borrow-checker

我有以下(删减)Rust 代码:

use std::collections::HashMap;

struct Node {
    weight:   f64,
    outbound: f64,
}

struct Graph {
    edges: HashMap<u32, HashMap<u32, f64>>,
    nodes: HashMap<u32, Node>,
}

impl Graph {
    fn mutate(&mut self) {
        for (key, value) in self.nodes.iter() {
            if self.edges.contains_key(key) {
                for (target, weight) in self.edges[key].iter() {
                    self.nodes.entry(*target).or_insert(Node::new()).weight;
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,由于 Rust 所有权规则(操场),我无法编译代码:

graph.rs:88:25: 88:35 error: cannot borrow `self.nodes` as mutable because it is also borrowed as immutable [E0502]
graph.rs:88                         self.nodes.entry(*target).or_insert(Node::new()).weight;
                                    ^~~~~~~~~~
Run Code Online (Sandbox Code Playgroud)

如果我更改要使用的第一个循环HashMap::iter_mut(),则会收到不同的错误(playground):

graph.rs:88:25: 88:35 error: cannot borrow `self.nodes` as mutable more than once at a time [E0499]
graph.rs:88                         self.nodes.entry(*target).or_insert(Node::new()).weight;
                                    ^~~~~~~~~~
Run Code Online (Sandbox Code Playgroud)

如何在 Rust 中实现这种带有突变的嵌套循环?

sta*_*lue 3

当您迭代数据结构时,无法在数据结构中插入或删除元素。

据我所知,Rust 迭代器也不支持修改(如 Java 迭代器remove())。

所以你有这些选择:

  • 如果只有很少的修改,您可以收集它们并在迭代完成后执行它们。

  • 如果大部分数据结构都被修改,或者数据结构足够小,复制的开销并不重要,则可以创建一个新的、修改后的数据结构,在迭代后替换原始数据结构。这通常是惯用的解决方案,在迭代器上使用高阶函数,例如map,flat_mapfilter

  • 这仍然是真的吗?听起来像是 Rust 这样的高性能语言的一个主要限制...... (2认同)