如何处理 HashMap 中的每个值并选择性地拒绝一些值?

mak*_*puf 3 rust borrow-checker

我想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
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

但这无法编译:

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
Run Code Online (Sandbox Code Playgroud)

我知道我真的需要https://github.com/rust-lang/rust/issues/27804(这是 forHashSet但 forHashMap是相同的)并且我无法在没有非 mut 和可变引用的情况下实现提供的解决方案仍然或使用不安全。

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

Joe*_*ley 5

注意如果您需要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"
}
Run Code Online (Sandbox Code Playgroud)