首页 > 解决方案 > 如何处理 HashMap 中的每个值并选择性地拒绝一些值?

问题描述

我想一个HashMap一个地处理这些值,同时可能删除其中的一些。

例如,我想做一个等价的:

use std::collections::HashMap;

fn example() {
    let mut to_process = HashMap::new();
    to_process.insert(1, true);

    loop {
        // get an arbitrary element
        let ans = to_process.iter().next().clone(); // get an item from the hash
        match ans {
            Some((k, v)) => {
                if condition(&k,&v) {
                    to_process.remove(&k);
                }
            }
            None => break, // work finished
        }
    }
}

但这无法编译:

error[E0502]: cannot borrow `to_process` as mutable because it is also borrowed as immutable
  --> src/lib.rs:12:17
   |
9  |         let ans = to_process.iter().next().clone();
   |                   ---------- immutable borrow occurs here
...
12 |                 to_process.remove(&k);
   |                 ^^^^^^^^^^^------^^^^
   |                 |          |
   |                 |          immutable borrow later used by call
   |                 mutable borrow occurs here

我知道我真的需要https://github.com/rust-lang/rust/issues/27804(这是 for HashSetbut forHashMap相同),如果没有非可变和可变引用,我无法实施提供的解决方案仍然或使用不安全。

有没有我想念的简单方法?

标签: rustborrow-checker

解决方案


注意如果您需要HashMap在处理过程中更改密钥或添加 kvps,请参阅@edwardw 的答案。除此以外 ...

使用HashMap::retain. 您可以更改流程函数以返回bool指示是否保留该键值对。例如

let mut to_process: HashMap<u32, String> = HashMap::new();
to_process.insert(1, "ok".to_string());
to_process.insert(2, "bad".to_string());

to_process.retain(process);
    
fn process(k: &u32, v: &mut String) -> bool {
    // do stuff with k and v
    v == "ok"
}

推荐阅读