lowdash/
map_keys.rs

1use std::collections::{BTreeMap, HashMap};
2
3/// Transforms the keys of a map using a provided function.
4///
5/// # Arguments
6/// * `map` - The input map whose keys are to be transformed.
7/// * `iteratee` - A function that takes a reference to a value and its key, returning a new key.
8///
9/// # Returns
10/// * `BTreeMap<R, V>` - A new map with transformed keys.
11///
12/// # Examples
13/// ```rust
14/// use lowdash::map_keys;
15/// use std::collections::HashMap;
16///
17/// let mut map = HashMap::new();
18/// map.insert("a", 1);
19/// map.insert("b", 2);
20/// let transformed = map_keys(&map, |&v, &k| format!("key_{}", k));
21/// assert_eq!(transformed.get("key_a"), Some(&1));
22/// assert_eq!(transformed.get("key_b"), Some(&2));
23/// ```
24pub fn map_keys<K, V, R, F>(map: &HashMap<K, V>, iteratee: F) -> BTreeMap<R, V>
25where
26    K: Eq + std::hash::Hash + Ord,
27    V: Clone,
28    R: Ord,
29    F: Fn(&V, &K) -> R,
30{
31    let mut result = BTreeMap::new();
32    let mut keys: Vec<&K> = map.keys().collect();
33
34    // Sort keys in descending order to ensure later keys overwrite earlier ones
35    keys.sort_by(|a, b| b.cmp(a));
36
37    for k in keys {
38        let v = &map[k];
39        let new_key = iteratee(v, k);
40        result.insert(new_key, v.clone());
41    }
42
43    result
44}
45
46#[cfg(test)]
47mod tests {
48    use super::*;
49    use std::collections::HashMap;
50
51    #[test]
52    fn test_map_keys() {
53        let mut map = HashMap::new();
54        map.insert("a", 1);
55        map.insert("b", 2);
56        let transformed = map_keys(&map, |&v, &k| format!("key_{}", k));
57        assert_eq!(transformed.get("key_a"), Some(&1));
58        assert_eq!(transformed.get("key_b"), Some(&2));
59    }
60
61    #[test]
62    fn test_map_keys_empty() {
63        let map: HashMap<&str, i32> = HashMap::new();
64        let transformed = map_keys(&map, |&v, &k| k.len());
65        assert!(transformed.is_empty());
66    }
67
68    #[test]
69    fn test_map_keys_overwrite() {
70        let mut map = HashMap::new();
71        map.insert("a", 1);
72        map.insert("A", 2); // "a" and "A" will both transform to "a"
73        let transformed = map_keys(&map, |&v, k| k.to_lowercase());
74        // Since keys are sorted in descending order, "a" is inserted first, then "A" overwrites it
75        assert_eq!(transformed.get("a"), Some(&2));
76    }
77}