1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
// from https://docs.rs/im/7.1.0/src/im/hashmap/mod.rs.html#584-590
use std::hash::Hash;
use std::collections::HashMap;

/// Merges two hashmaps, using f where the keys exist in both hashmaps
/// * one: The first hashmap
/// * two: The second hashmap
/// * f: What to do when the key exists in both hashmaps
/// * Returns: The union of one and two
pub fn union_of<K, V, F>(one: &HashMap<K, V>, two: &HashMap<K, V>, f: F) -> HashMap<K, V>
where
    K: Hash + Eq + Clone,
    V: Clone,
    F: Fn(V, V) -> V
{
    two
        .iter()
        .fold(one.clone(), |mut m: HashMap<K, V>, (k, v)| {
                m.insert(
                    k.clone(),
                    one.get(k).map(|v1: &V| f(v1.clone(), v.clone())).unwrap_or(v.clone())
                );
                m
            }
        )
}

/// Gets the intersection of two HashMaps, using f to join them
/// * one: The first hashmap
/// * two: The second hashmap
/// * f: What to do when the key exists in both hashmaps
/// * Returns: The intersection of one and two
pub fn intersection_of<K, A, B, C, F>(one: &HashMap<K, A>, two: &HashMap<K, B>, f: F) -> HashMap<K, C>
where
    K: Hash + Eq + Clone,
    A: Clone,
    B: Clone,
    F: Fn(A, B) -> C
{
    let mut out = HashMap::new();
    for (k, v2) in two {
        match one.get(k) {
            None => (),
            Some(v1) => {
                let result = f(v1.clone(), v2.clone());
                out.insert(k.clone(), result);
            }
        }
    }
    out
}