mckernant1_tools/iter/
counting.rs1use std::collections::HashMap;
2use std::hash::Hash;
3
4pub trait EachCount {
5 type Item;
6
7 fn each_count(self) -> HashMap<Self::Item, u64>
9 where
10 Self::Item: Hash + Eq;
11
12 fn each_count_by<K>(self, selector: fn(Self::Item) -> K) -> HashMap<K, u64>
15 where
16 K: Eq + Hash;
17}
18
19impl<I, T> EachCount for I
20where
21 I: IntoIterator<Item = T>,
22{
23 type Item = T;
24
25 fn each_count(self) -> HashMap<Self::Item, u64>
26 where
27 Self::Item: Hash + Eq,
28 {
29 let mut hm: HashMap<Self::Item, u64> = HashMap::new();
30
31 for item in self.into_iter() {
32 hm.entry(item).and_modify(|it| *it += 1).or_insert(1);
33 }
34 hm
35 }
36
37 fn each_count_by<K>(self, selector: fn(Self::Item) -> K) -> HashMap<K, u64>
38 where
39 K: Eq + Hash,
40 {
41 let mut hm: HashMap<K, u64> = HashMap::new();
42
43 for item in self.into_iter().map(|it| selector(it)) {
44 hm.entry(item).and_modify(|it| *it += 1).or_insert(1);
45 }
46 hm
47 }
48}
49
50#[cfg(test)]
51mod test {
52 use crate::iter::counting::EachCount;
53 use std::collections::HashMap;
54
55 #[derive(Clone, Hash, PartialEq, Eq, Debug)]
56 struct Test {
57 a: i64,
58 b: u64,
59 }
60
61 #[test]
62 fn test_each_count() {
63 let v = vec![1, 1, 1, 2, 3, 3, 3, 3];
64 let v = v.each_count();
65
66 assert_eq!(v, HashMap::from([(1, 3), (2, 1), (3, 4)]))
67 }
68
69 #[test]
70 fn test_each_count_by() {
71 let v = vec![
72 Test { a: 1, b: 1 },
73 Test { a: 1, b: 2 },
74 Test { a: 1, b: 2 },
75 Test { a: 2, b: 1 },
76 Test { a: 3, b: 1 },
77 Test { a: 3, b: 2 },
78 Test { a: 3, b: 2 },
79 Test { a: 3, b: 2 },
80 ];
81 let x = v.clone().each_count();
82 assert_eq!(
83 x,
84 HashMap::from([
85 (Test { a: 3, b: 2 }, 3),
86 (Test { a: 1, b: 2 }, 2),
87 (Test { a: 1, b: 1 }, 1),
88 (Test { a: 3, b: 1 }, 1),
89 (Test { a: 2, b: 1 }, 1)
90 ])
91 );
92 let v = v.each_count_by(|it| it.a);
93 assert_eq!(v, HashMap::from([(1, 3), (2, 1), (3, 4)]))
94 }
95}