锈蚀检查借用整个HashMap,不检查密钥,有什么好办法吗



我想移动HashMap<u64、Vec>key=1到key=2

use std::collections::HashMap;
fn main() {
let mut arr: HashMap<u64, Vec<u64>> = HashMap::new();
arr.insert(1, vec![10, 11, 12]); // in fact, elments more than 1,000,000, so can't use clone()
arr.insert(2, vec![20, 21, 22]);
// in fact, following operator is in recusive closure, I simplify the expression:
let mut vec1 = arr.get_mut(&1).unwrap();
let mut vec2 = arr.get_mut(&2).unwrap();
// move the elements of key=1 to key=2
for v in vec1 {
vec2.push(vec1.pop().unwrap());
}
}

得到错误:

error[E0499]: cannot borrow `arr` as mutable more than once at a time
--> src/main.rs:10:20
|
9  |     let mut vec1 = arr.get_mut(&1).unwrap();
|                    --- first mutable borrow occurs here
10 |     let mut vec2 = arr.get_mut(&2).unwrap();
|                    ^^^ second mutable borrow occurs here
11 |     for v in vec1 {
|              ---- first borrow later used here

Rust检查借用了整个HashMap,而不是检查密钥。有什么好办法吗?

尚不清楚上下文/约束是什么,因此根据这些约束,有各种不同影响和复杂程度的可能性

  • 如果您不关心保留第一个条目的空版本,您可以只使用HashMap::remove,因为它返回已删除键的值:https://play.rust-lang.org/?version=stable&mode=调试&edition=2018&gist=1734142acb598bad2f460fdff028b6e
  • 否则,可以使用类似mem::swap的东西将键1持有的向量替换为空向量,然后可以更新键2持有的向量:https://play.rust-lang.org/?version=stable&mode=调试&edition=2018&gist=e05941cb4d7df8982af7c9437a0446
  • 由于HashMap没有拆分,最后的选择是使用可变迭代器,迭代器本质上是不重叠的,因此它们提供了对单个值的可变引用,这意味着它们可以让您同时获得对两个值的可变参考,尽管代码要复杂得多:https://play.rust-lang.org/?version=stable&mode=调试&edition=2018&要点=87d3c0a151882ce2f47dda59dc089d70

虽然第三个选项必须遍历整个哈希图(这比通过哈希直接找到正确的条目效率低(,但它可能的优点是:;失去";v1的分配,如果v1将来会再次填充,这是有用的:在第一个选项中,v1被完全删除,在第二个选项中v1变成容量为0的向量(除非你交换了一个具有预定义容量的向量,但这仍然是一个额外的分配(

您可以将Vec放入RefCell中,将借用检查移动到运行时:

use std::cell::RefCell;
use std::collections::HashMap;
fn main() {
let mut arr: HashMap<u64, RefCell<Vec<u64>>> = HashMap::new();
arr.insert(1, RefCell::new(vec![10, 11, 12])); // in fact, elments more than 1,000,000, so can't use clone()
arr.insert(2, RefCell::new(vec![20, 21, 22]));
// in fact, following operator is in recusive closure, I simplify the expression:
let mut vec1 = arr.get(&1).unwrap().borrow_mut();
let mut vec2 = arr.get(&2).unwrap().borrow_mut();
// move the elements of key=1 to key=2
vec2.append(&mut vec1);
}

提示:使用Vec::append将值从一个矢量移动到另一个矢量。

最新更新