Rust check borrow with the whole HashMap, not check the key,有什么好办法吗?
Rust check borrow with the whole HashMap, not check the key, is there any good way?
我想将 HashMap 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
as it returns the value for the removed key: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=1734142acb598bad2ff460fdff028b6e
- 否则,您可以使用
mem::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=e05941cb4d7ddf8982baf7c9437a0446
- 因为
HashMap
没有拆分,最后的选择是使用可变迭代器,迭代器本质上是不重叠的,所以它们提供对单个值的可变引用,这意味着它们可以让你获得可变的同时引用两个值,尽管代码要复杂得多:https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=87d3c0a151382ce2f47dda59dc089d70
虽然第三个选项必须遍历整个散列映射(这比直接通过散列找到正确的条目效率低),但它具有不会“丢失”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
将值从一个向量移动到另一个向量。
我想将 HashMap
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
as it returns the value for the removed key: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=1734142acb598bad2ff460fdff028b6e - 否则,您可以使用
mem::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=e05941cb4d7ddf8982baf7c9437a0446 - 因为
HashMap
没有拆分,最后的选择是使用可变迭代器,迭代器本质上是不重叠的,所以它们提供对单个值的可变引用,这意味着它们可以让你获得可变的同时引用两个值,尽管代码要复杂得多:https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=87d3c0a151382ce2f47dda59dc089d70
虽然第三个选项必须遍历整个散列映射(这比直接通过散列找到正确的条目效率低),但它具有不会“丢失”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
将值从一个向量移动到另一个向量。