如何在 Rust 中实现 HashMap 上带有突变的嵌套循环?
How can a nested loop with mutations on a HashMap be achieved in Rust?
我有以下(精简)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;
}
}
}
}
}
但是,由于 Rust 所有权规则 (playground),我无法编译代码:
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;
^~~~~~~~~~
如果我将第一个循环更改为使用 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;
^~~~~~~~~~
这种带有突变的嵌套循环如何在 Rust 中实现?
在迭代数据结构时不能在数据结构中插入或删除元素。
据我所知,Rust 迭代器也不支持修改(比如 Java 迭代器的 remove()
)。
所以你剩下这些选项:
如果只有少量修改,可以收集起来,等迭代结束后再执行。
如果大部分数据结构被修改,或者如果它足够小以至于复制的开销无关紧要,您可以创建一个新的修改后的数据结构来替换原来的数据结构迭代。这通常是惯用的解决方案,在 map
、flat_map
或 filter
.
等迭代器上使用高阶函数
我有以下(精简)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;
}
}
}
}
}
但是,由于 Rust 所有权规则 (playground),我无法编译代码:
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;
^~~~~~~~~~
如果我将第一个循环更改为使用 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;
^~~~~~~~~~
这种带有突变的嵌套循环如何在 Rust 中实现?
在迭代数据结构时不能在数据结构中插入或删除元素。
据我所知,Rust 迭代器也不支持修改(比如 Java 迭代器的 remove()
)。
所以你剩下这些选项:
如果只有少量修改,可以收集起来,等迭代结束后再执行。
如果大部分数据结构被修改,或者如果它足够小以至于复制的开销无关紧要,您可以创建一个新的修改后的数据结构来替换原来的数据结构迭代。这通常是惯用的解决方案,在
map
、flat_map
或filter
. 等迭代器上使用高阶函数