counter_fpy/
lib.rs

1// Author: blackprince001
2// Implementation of Python Counter Module
3// https://docs.python.org/3/library/collections.html?highlight=counter#collections.Counter
4
5use 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        // sort by descending order with counts from each
91        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}