【问题标题】:Rust check borrow with the whole HashMap, not check the key, is there any good way?Rust 校验借用整个HashMap,不校验key,有什么好办法吗?
【发布时间】:2020-11-19 08:42:37
【问题描述】:

我想将 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,而不是检查密钥。 有什么好办法吗?

【问题讨论】:

    标签: rust hashmap borrow


    【解决方案1】:

    目前尚不清楚上下文/约束是什么,因此取决于这些,存在不同影响和复杂程度的各种可能性

    虽然第三个选项必须遍历整个 hashmap(这比通过散列直接找到正确的条目效率低),但它可能具有不会“丢失”v1 的分配的优势,这在 v1 将被再次填充时很有用未来:在第一个选项中,v1 被完全删除,在第二个选项中,v1 成为容量为 0 的向量(除非您交换具有预定义容量的向量,但这仍然是额外分配)

    【讨论】:

    • remove() 解决了我的问题,你让我学到更多知识,谢谢。
    • 请考虑将一些建议的选项粘贴到答案中(如果您想节省空间,可能只是第一个选项)。 Playground 链接是场外资源,最适合作为答案的附加组件,应该独立存在。
    【解决方案2】:

    您可以将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 将值从一个向量移动到另一个向量。

    【讨论】:

    • RefCell 很神奇!看起来它突破了 Rust 的借用检查。在递归闭包中,信号线程中不需要 Mutex::lock() 变量(看起来不合理)。是一个很好的解决方案!谢谢!
    • @Anunaki RefCell 是“神奇的”,因为它在运行时而不是编译时进行借用检查,这意味着成本。如果对象已经与尝试不兼容地被借用,borrowborrow_mut 将使程序崩溃(try_ 版本将返回 Err)。
    猜你喜欢
    • 2012-10-24
    • 1970-01-01
    • 2021-03-20
    • 2012-12-06
    • 2015-06-29
    • 2011-03-22
    • 2021-11-29
    • 2012-12-30
    • 2023-03-22
    相关资源
    最近更新 更多