[英]Rust check borrow with the whole HashMap, not check the key, is there any good way?
I want move the elements of HashMap<u64, Vec> key=1 to key=2我想将 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());
}
}
got error:得到错误:
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 check borrow with the whole HashMap, not check the key. Rust 检查借用整个 HashMap,而不是检查键。 Is there any good way ?
有什么好办法吗?
It's not clear what the context / constraints are, so depending on those there are various possibilities of different impact and levels of complexity不清楚上下文/约束是什么,因此根据这些,存在不同影响和复杂程度的各种可能性
HashMap::remove
as it returns the value for the removed key: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=1734142acb598bad2ff460fdff028b6eHashMap::remove
因为它返回已删除键的值: https : //play.rust-lang.org/? version =stable&mode =调试&版本=2018&gist=1734142acb598bad2ff460fdff028b6emem::swap
to swap the vector held by key 1 with an empty vector, then you can update the vector held by key 2: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=e05941cb4d7ddf8982baf7c9437a0446mem::swap
类的东西将键 1 持有的向量与空向量交换,然后您可以更新键 2 持有的向量: https : //play.rust-lang.org/?version=稳定&模式=调试&版本=2018&gist=e05941cb4d7ddf8982baf7c9437a0446HashMap
doesn't have splits, the final option would be to use a mutable iterator, iterators are inherently non-overlapping so they provide mutable references to individual values, meaning they would let you obtain mutable references to both values simultanously, though the code is a lot more complicated: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=87d3c0a151382ce2f47dda59dc089d70HashMap
没有拆分,最后的选择是使用可变迭代器,迭代器本质上是不重叠的,因此它们提供对单个值的可变引用,这意味着它们可以让您同时获得对两个值的可变引用,尽管代码复杂得多: https : //play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=87d3c0a151382ce2f47dda59dc089d70 While the third option has to traverse the entire hashmap (which is less efficient than directly finding the correct entries by hashing), it has the possible advantage of not "losing" v1's allocation which is useful if v1 will be filled again in the future: in the first option v1 is completely dropped, and in the second option v1 becomes a vector of capacity 0 (unless you swap in a vector with a predefined capacity, but that's still an extra allocation)虽然第三个选项必须遍历整个 hashmap(这比直接通过散列找到正确的条目效率低),但它具有不“丢失”v1 的分配的可能优势,如果 v1 将来再次填充,这很有用:在第一个选项中 v1 被完全删除,在第二个选项中 v1 成为容量为 0 的向量(除非您交换具有预定义容量的向量,但这仍然是额外的分配)
You can put the Vec
into a RefCell
moving the borrow check to runtime:您可以将
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);
}
Tip: Use Vec::append
which moves the values from one vector to another.提示:使用
Vec::append
将值从一个向量移动到另一个向量。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.