如果HashMap为空,那么从HashMap中删除一个值有什么惯用的方法?

8
以下代码可用,但是由于 is_empty 的定义太远,使用起来不够美观。
fn remove(&mut self, index: I, primary_key: &Rc<K>) {
    let is_empty;
    {
        let ks = self.data.get_mut(&index).unwrap();
        ks.remove(primary_key);
        is_empty = ks.is_empty();
    }
    // I have to wrap `ks` in an inner scope so that we can borrow `data` mutably.
    if is_empty {
        self.data.remove(&index);
    }
}

我们有没有一些方法在进入if分支之前删除条件中的变量,例如:

if {ks.is_empty()} {
    self.data.remove(&index);
}
2个回答

14

每当你需要对一个键进行双重查找时,你需要考虑使用Entry API

通过 Entry API,你可以获取到一个键值对的句柄,并且可以:

  • 读取键,
  • 读取或修改值,
  • 完全删除条目(获取键和值)。

它非常强大。

在这种情况下:

use std::collections::HashMap;
use std::collections::hash_map::Entry;

fn remove(hm: &mut HashMap<i32, String>, index: i32) {
    if let Entry::Occupied(o) = hm.entry(index) {
        if o.get().is_empty() {
            o.remove_entry();
        }
    }
}

fn main() {
    let mut hm = HashMap::new();
    hm.insert(1, String::from(""));

    remove(&mut hm, 1);

    println!("{:?}", hm);
}

我尝试使用Entry API,但在我的用例中遇到了困难,即首先修改值,然后,如果修改后的值满足某些条件/变为空,则从哈希映射中删除它。这种方法行不通吗? - xji
1
@xij:这非常接近Shepmaster的下面的答案。只要小心你借用的范围,也就是将修改封装在块{ let key = occupied.get_mut();/*更改*/ }中,然后进行检查/删除。 - Matthieu M.
试图给予应有的荣誉,下面的答案是原帖作者的,他们只是把它放在了问题中。他们选择不将其移动到自己的答案中,所以我替他们做了(这就是为什么它是社区维基)。 - Shepmaster

6

最终我做了这个:

match self.data.entry(index) {
    Occupied(mut occupied) => {
        let is_empty = {
            let ks = occupied.get_mut();
            ks.remove(primary_key);
            ks.is_empty()
        };
        if is_empty {
            occupied.remove();
        }

    },
    Vacant(_) => unreachable!()
}

1
这种方法适合我的用例,先修改值,然后确定是否删除它。被接受的答案似乎无法做到这一点。 - xji
你为什么把这个社区变成了维基?你回答自己的问题仍然应该得到声望。 - Matt Joiner
@MattJoiner,此问题并非由OP发布,而是我发布的。不幸的是,OP在问题中回答了自己的问题,因此我将其移动到答案部分,以便可以单独进行投票。我不应该从中获得声望,所以这是一个公共社区Wiki。这也被提及在上面 - Shepmaster

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接