【问题标题】:Is it possible to detect collisions when collecting into a HashMap?收集到 HashMap 时是否可以检测到冲突?
【发布时间】:2022-01-21 17:08:01
【问题描述】:

我想在将IntoIterator 收集到HashMap 时检测并警告日志中的冲突。当前 Rust 收集到 HashMap 的行为是用最新的值静默覆盖早期的值。

fn main() {
    let a = vec![(0, 1), (0, 2)];
    let b: std::collections::HashMap<_, _> = a.into_iter().collect();
    println!("{}", b[&0]);
}

输出:

2

(Playground)

一种可能的解决方法是收集到Vec,然后手动编写转换代码,但这会引入额外的分配开销和不可读的代码。不消耗原始集合并比较 len()s 的噪音较小,但仍会占用多 1 倍的内存(?)并且无法检测到碰撞发生的确切位置。

有没有更优雅的方式来处理HashMap 冲突?

【问题讨论】:

    标签: rust hashmap


    【解决方案1】:

    根据您在发生碰撞时要执行的操作,您可以使用fold(或try_fold)和entry API 来实现您的自定义功能:

    use std::collections::HashMap;
    
    fn main() {
        let a = vec![(0, 1), (0, 3), (0, 2)];
    
        let b: std::collections::HashMap<_, _> = a.into_iter().fold(HashMap::new(), |mut map, (k,v)| {
            map.entry(k)
                .and_modify(|_| println!("Collision with {}, {}!", k, v))
                .or_insert(v);
            map
        });
    
        println!("{}", b[&0]);
    }
    

    (Playground)

    【讨论】:

    • 我建议不要使用 contains_key + .get().unwrap() 来使用 if let.get(): if let Some(&amp;other_value) = map.get(&amp;k) { if v &gt; other_value { map.insert(k, v); } } else { map.insert(k, v); }
    • entry API 可以说是一种更清洁的方法。 Playground
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多