< 返回版块

rascalrr 发表于 2022-08-18 17:30

Tags:HashMap

fn test_4() {
    use std::collections::HashMap;
    let mut maps: std::collections::HashMap<String, i32> = HashMap::new();

    maps.insert("1".to_owned(), 1);
    maps.insert("2".to_owned(), 2);
    maps.insert("3".to_owned(), 3);

    if let Some(v2) = maps.iter().find(|f| *f.1 == 2) {
        maps.remove_entry(v2.0);
    }    

error[E0502]: cannot borrow `maps` as mutable because it is also borrowed as immutable
}

比如有这么一个哈希表,我想检索到值为2的项并删除它。

我理解报错信息的意义,也知道clone一个哈希表并转成列表再检索可以解决这个问题。

但我想知道在实际的需求中遇到这种情况,应该怎么做才是最优的?

评论区

写评论
作者 rascalrr 2022-08-19 09:23

嗯,嗯。这个方案也很好,相比较clone这个map,clone一个key的开销小多了。

--
👇
Pikachu: 遇事不决就clone。(不是最好的,但是我还得翻翻docs,所以先给个简单版的)

if let Some(v2) = maps.iter().find(|f| *f.1 == 2) {      
    maps.remove_entry(&v2.0.clone());
}

playground

作者 rascalrr 2022-08-19 09:22

感谢~

--
👇
Bai-Jinlin: https://doc.rust-lang.org/stable/std/collections/hash_map/struct.HashMap.html#method.retain

作者 rascalrr 2022-08-19 09:21

感谢,试了下retain,确实可行。

--
👇
Pikachu: 翻完docs发现还是上面Bai-Jinlin提到的retain最好。

retain唯一的问题是时间复杂度O(capacity),但是你都已经用iter了,时间复杂度已经是O(capacity),那就没什么好担心的了。

Retain的实现在这里,本质上也是iter,不过它用了unsafe。

https://github.com/rust-lang/hashbrown/blob/1d2c1a81d1b53285decbd64410a21a90112613d7/src/map.rs#L826

Pikachu 2022-08-19 00:42

翻完docs发现还是上面Bai-Jinlin提到的retain最好。

retain唯一的问题是时间复杂度O(capacity),但是你都已经用iter了,时间复杂度已经是O(capacity),那就没什么好担心的了。

Retain的实现在这里,本质上也是iter,不过它用了unsafe。

https://github.com/rust-lang/hashbrown/blob/1d2c1a81d1b53285decbd64410a21a90112613d7/src/map.rs#L826

Pikachu 2022-08-19 00:05

遇事不决就clone。(不是最好的,但是我还得翻翻docs,所以先给个简单版的)

if let Some(v2) = maps.iter().find(|f| *f.1 == 2) {      
    maps.remove_entry(&v2.0.clone());
}

playground

gorust21 2022-08-18 20:03

提示得很清楚了

Bai-Jinlin 2022-08-18 17:39

https://doc.rust-lang.org/stable/std/collections/hash_map/struct.HashMap.html#method.retain

1 共 7 条评论, 1 页