1use std::{collections::HashMap, panic};
6
7#[derive(PartialEq, Eq, Clone)]
8pub struct Counter<
9 T: std::cmp::Eq + std::hash::Hash + std::marker::Copy + std::cmp::PartialOrd + std::cmp::PartialEq,
10> {
11 table: HashMap<T, usize>,
12}
13
14impl<
15 T: std::cmp::Eq
16 + std::hash::Hash
17 + std::marker::Copy
18 + std::cmp::PartialOrd
19 + std::cmp::PartialEq,
20 > Default for Counter<T>
21{
22 fn default() -> Self {
23 Counter {
24 table: HashMap::new(),
25 }
26 }
27}
28
29impl<
30 T: std::cmp::Eq
31 + std::hash::Hash
32 + std::marker::Copy
33 + std::cmp::PartialOrd
34 + std::cmp::PartialEq,
35 > Counter<T>
36{
37 pub fn new() -> Self {
38 Counter {
39 table: HashMap::new(),
40 }
41 }
42
43 pub fn from(mut self, iterable: impl IntoIterator<Item = T> + std::clone::Clone) -> Counter<T> {
44 for item in iterable.clone().into_iter() {
45 if self.table.contains_key(&item) {
46 *self.table.get_mut(&item).unwrap() += 1;
47 continue;
48 }
49 self.table.insert(item, 1);
50 }
51
52 Counter { table: self.table }
53 }
54
55 pub fn get(&self, key: T) -> Option<usize> {
56 if self.table.contains_key(&key) {
57 self.table.get(&key).copied()
58 } else {
59 Some(0)
60 }
61 }
62
63 pub fn update(&mut self, key: T, count: usize) {
64 self.table.insert(key, count);
65 }
66
67 pub fn elements(&self) -> impl IntoIterator<Item = T> {
68 let mut vector = vec![];
69 for (item, count) in &self.table {
70 for _ in 0..*count {
71 vector.push(*item);
72 }
73 }
74
75 vector.into_iter()
76 }
77
78 pub fn iter(&self) -> impl Iterator<Item = (&T, &usize)> {
79 self.table.iter()
80 }
81
82 pub fn most_common(&self, n: usize) -> Vec<(&T, &usize)> {
83 if n > self.table.keys().len() {
84 panic!("{n} Exceeds the number of unique items in our Counter Struct.")
85 }
86
87 let mut iter = self.table.iter().collect::<Vec<_>>();
88 let mut slice = vec![];
89
90 iter.sort_by(|a, b| (b.1).partial_cmp(a.1).unwrap());
92 iter[..n].clone_into(&mut slice);
93
94 slice
95 }
96
97 pub fn substract(&self, other: &Self) -> Counter<T> {
98 let mut ctmp = Counter::new();
99
100 for (self_key, self_count) in &self.table {
101 for (other_key, other_count) in &other.table {
102 if self_key == other_key {
103 ctmp.update(
104 *self_key,
105 if self_count > other_count {
106 *self_count - *other_count
107 } else {
108 *other_count - *self_count
109 },
110 )
111 }
112 }
113 }
114 ctmp
115 }
116
117 pub fn total(&self) -> usize {
118 let total_count: usize = self.table.values().sum();
119
120 total_count
121 }
122
123 pub fn clear(&mut self) {
124 self.table.clear()
125 }
126}