Skip to main content

h_math/
functionality.rs

1use std::collections::{HashMap, HashSet};
2use std::hash::Hash;
3use std::iter::zip;
4
5
6#[derive(Debug)]
7pub enum ListToHashMapError<K> {
8    LengthMismatch { keys_len: usize, values_len: usize },
9    DuplicateKeys { duplicates: Vec<K> },
10}
11
12
13/// This trait converts the values of a HashMap into a HashSet. The values must implement the Eq, Hash, 
14/// and Clone traits to be stored in a HashSet. The function will return a HashSet containing all the unique values 
15/// from the HashMap. For example, if the HashMap contains the pairs (1, "a"), (2, "b"), and (3, "a"), 
16/// the resulting HashSet will contain "a" and "b", because "a" is duplicated in the values of the HashMap.
17/// Example usage:
18/// let mut map = HashMap::new();
19/// map.insert(1, "a");
20/// map.insert(2, "b");
21/// map.insert(3, "a");
22/// let value_set = map.h_hashmap_values_to_hashset();
23/// The result will be a HashSet containing "a" and "b", because those are the unique values in the HashMap.
24pub trait HashMapValuesToHashSet<V>
25where
26    V: Eq + Hash + Clone,
27{
28    fn h_hashmap_values_to_hashset(&self) -> HashSet<V>;
29}
30
31impl<K, V> HashMapValuesToHashSet<V> for HashMap<K, V>
32where
33    V: Eq + Hash + Clone,
34{
35    fn h_hashmap_values_to_hashset(&self) -> HashSet<V> {
36        let mut set: HashSet<V> = HashSet::new();
37        for (_key, value) in self.iter() {
38            set.insert(value.clone());
39        }
40        set
41    }
42}
43
44
45/// This trait converts the keys of a HashMap into a HashSet. The keys must implement the Eq, Hash, 
46/// and Clone traits to be stored in a HashSet. The function will return a HashSet
47/// containing all the unique keys from the HashMap. For example, if the HashMap contains the pairs (1, "a"), (2, "b"), 
48/// and (3, "a"),
49/// the resulting HashSet will contain 1, 2, and 3, because those are the unique keys in the HashMap.
50/// Example usage:
51/// let mut map = HashMap::new();
52/// map.insert(1, "a");
53/// map.insert(2, "b");
54/// map.insert(3, "a");
55/// let key_set = map.h_hashmap_keys_to_hashset();
56/// The result will be a HashSet containing 1, 2, and 3, because those are the unique keys in the HashMap.
57pub trait HashMapKeysToHashSet<K>
58where
59    K: Eq + Hash + Clone,
60{
61    fn h_hashmap_keys_to_hashset(&self) -> HashSet<K>;
62}
63
64impl<K, V> HashMapKeysToHashSet<K> for HashMap<K, V>
65where
66    K: Eq + Hash + Clone,
67{
68    fn h_hashmap_keys_to_hashset(&self) -> HashSet<K> {
69        let mut set: HashSet<K> = HashSet::new();
70        for (key, _value) in self.iter() {
71            set.insert(key.clone());
72        }
73        set
74    }
75}
76
77
78/// This function converts a list of keys and a list of values into a HashMap.
79/// The keys and values must implement the Eq, Hash, and Clone traits to be stored in a HashMap.
80/// The function will return a Result containing a HashMap where each key from the list of keys is associated with the corresponding value
81/// from the list of values, or a vector of errors if issues are found (length mismatch or duplicate keys).
82/// For example, if the list of keys is [1, 2, 3] and the list of values is ["a", "b", "c"],
83/// the resulting HashMap will contain the pairs (1, "a"), (2, "b"), and (3, "c").
84/// If lengths don't match or there are duplicate keys, it returns errors.
85/// Example usage:
86/// let keys = vec![1, 2, 3];
87/// let values = vec!["a", "b", "c"];
88/// let map = h_list_to_hashmap(&keys, &values);
89/// The result will be Ok(HashMap) containing the pairs (1, "a"), (2, "b"), and (3, "c").
90
91pub fn h_list_to_hashmap<K, V>(keys: &[K], values: &[V]) -> Result<HashMap<K, V>, Vec<ListToHashMapError<K>>>
92where
93    K: Eq + Hash + Clone,
94    V: Clone,
95{
96    if keys.len() != values.len() {
97        return Err(vec![ListToHashMapError::LengthMismatch {
98            keys_len: keys.len(),
99            values_len: values.len(),
100        }]);
101    }
102
103    let mut map = HashMap::new();
104    let mut duplicates = Vec::new();
105
106    for (key, value) in keys.iter().zip(values.iter()) {
107        if map.contains_key(key) {
108            duplicates.push(key.clone());
109        } else {
110            map.insert(key.clone(), value.clone());
111        }
112    }
113
114    if !duplicates.is_empty() {
115        return Err(vec![ListToHashMapError::DuplicateKeys {
116            duplicates,
117        }]);
118    }
119
120    Ok(map)
121}
122
123
124
125
126
127/// this trait converts a list of values into a HashSet. 
128/// The values must implement the Eq, Hash, and Clone traits to be stored in a HashSet.
129/// The function will return a tuple of (HashSet containing all the unique values from the list, number of duplicates removed). 
130/// For example, if the list contains ["a", "b", "a", "c"],
131/// the result will be (HashSet containing "a", "b", "c", 1), because "a" was duplicated.
132/// Example usage:
133/// let values = vec!["a", "b", "a", "c"];
134/// let (value_set, dupes) = values.h_list_to_hashset();
135/// value_set will contain "a", "b", "c", and dupes will be 1.
136
137pub trait ListToHashSet {
138    type Item;
139
140    fn h_list_to_hashset(&self) -> (HashSet<Self::Item>, usize)
141    where
142        Self::Item: Eq + Hash + Clone;
143}
144
145impl<T> ListToHashSet for [T]
146where
147    T: Eq + Hash + Clone,
148{
149    type Item = T;
150
151    fn h_list_to_hashset(&self) -> (HashSet<Self::Item>, usize) {  
152        let mut set = HashSet::new();
153        let mut duplicates = 0;
154        for item in self.iter() {
155            if !set.insert(item.clone()) {
156                duplicates += 1;
157            }
158        }
159        (set, duplicates)
160    }
161}
162
163use std::time::Duration;
164
165#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
166pub struct HBlockPreformance {
167    label: Option<&'static str>,
168    duration: Duration,
169    file: &'static str,
170    line: u32,
171}
172
173impl HBlockPreformance {
174    pub fn new() -> Self {
175        HBlockPreformance { label: None, duration: Duration::new(0, 0), line: 0, file: "" }
176    }
177    pub fn set_new(label: Option<&'static str>, duration: Duration, line: u32, file: &'static str) -> Self {
178        HBlockPreformance { label: label, duration: duration, line: line, file: file}
179    }
180    pub fn print(&self) {
181        println!("label: {:?}, duration: {:?}, line: {}, file: {}", self.label, self.duration, self.line, self.file);
182    }
183    pub fn print_fields_specified(&self, fields: &[HBlockPreformanceField]) {
184        let mut count: usize = 1;
185        if fields.contains(&HBlockPreformanceField::Label) {
186            if fields.len() == count {
187                print!("label: {:?}\n", self.label);
188            }
189            else {
190                print!("label: {:?}, ", self.label);
191            }
192            count += 1;
193        } 
194        if fields.contains(&HBlockPreformanceField::Duration) {
195            if fields.len() == count {
196                print!("duration: {:?}\n", self.duration);
197            }
198            else {
199                print!("duration: {:?}, ", self.duration);
200            }
201            count += 1;
202        }
203        if fields.contains(&HBlockPreformanceField::File) {
204            if fields.len() == count {
205                print!("file: {:?}\n", self.file);
206            }
207            else {
208                print!("file: {:?}, ", self.file);
209            }
210        }
211        if fields.contains(&HBlockPreformanceField::Line) {
212            print!("line: {:?}\n", self.line);
213        }
214    }
215    pub fn print_label(&self) {
216        println!("label: {:?}", self.label);
217    }
218    pub fn print_duration(&self) {
219        println!("duration: {:?}", self.duration);
220    }
221    pub fn print_file(&self) {
222        println!("label: {}", self.file);
223    }
224    pub fn print_line(&self) {
225        println!("line: {}", self.line);
226    }
227}
228
229
230#[macro_export]
231macro_rules! h_block_preformance {
232    ($code:block) => {
233        {
234            let start = std::time::Instant::now();
235            $code
236            HBlockPreformance::set_new(None, start.elapsed(), line!(), file!())
237        }
238    };
239}
240
241
242#[derive(Debug, PartialEq, Eq)]
243pub enum HBlockPreformanceLogPrintOrder {
244    Normal,
245
246    LabelAlphabeticAscending,
247
248    DurationAscending,
249
250    FileAlphabeticalAscending,
251
252    LineAscending,
253}
254
255
256#[derive(Debug, PartialEq, Eq)]
257pub enum HBlockPreformanceField {
258    Label,
259    Duration,
260    File,
261    Line,
262}
263
264
265/* 
266#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
267pub struct HBlockPreformanceLog {
268    log: Vec<HBlockPreformance>,
269    labels: Vec<Option<&'static str>>,
270    files: Vec<&'static str>,
271    lines: Vec<u32>,
272}
273
274impl HBlockPreformanceLog {
275    pub fn new() -> Self {
276        HBlockPreformanceLog { log: Vec::new(), labels: Vec::new(), files: Vec::new(), lines: Vec::new() }
277    }
278    pub fn push(&mut self, new: HBlockPreformance) {
279        if cfg!(debug_assertions) {
280            self.labels.push(new.label);
281            self.files.push(new.file);
282            self.lines.push(new.line);
283            self.log.push(new);
284        }
285    }
286    fn find_new_indecies(&self, field: HBlockPreformanceField, old_vec: &Vec<&HBlockPreformance>, new_vec: &Vec<&HBlockPreformance>) -> Vec<usize> { // returns &[(old index, new index)]
287        let mut indecies: Vec<usize> = Vec::new();
288        for i in old_vec {
289            let mut new_index: usize = 0;
290            
291            for j in new_vec {
292                if field == HBlockPreformanceField::Label {
293                    if i.label == j.label {
294                        new_index += 1;
295                        break;
296                    }
297                }
298                if field == HBlockPreformanceField::Duration {
299                    if i.duration == j.duration {
300                        new_index += 1;
301                        break;
302                    }
303                }
304                if field == HBlockPreformanceField::File {
305                    if i.file == j.file {
306                        new_index += 1;
307                        break;
308                    }
309                }
310                if field == HBlockPreformanceField::Line {
311                    if i.line == j.line {
312                        new_index += 1;
313                        break;
314                    }
315                }
316            }
317            indecies.push(new_index);
318        }
319        indecies
320    }
321    fn ordered_list<'a>(&self, new_indecies: Vec<usize>, normal_ref_list: &Vec<&'a HBlockPreformance>) -> Vec<&'a HBlockPreformance> {
322        let mut ordered: Vec<&'a HBlockPreformance> = Vec::new();
323        for index in new_indecies {
324            ordered.push(normal_ref_list[index]);
325        }
326        ordered
327    }
328    
329    
330    pub fn print(&self, order: HBlockPreformanceLogPrintOrder, fields_included: &[HBlockPreformanceField]) {
331        if cfg!(debug_assertions) {
332            let mut ordered_blocks: Vec<&HBlockPreformance> = Vec::new();
333            let logged_blocks: Vec<&HBlockPreformance> = self.log.iter().collect();
334           
335            
336            if order == HBlockPreformanceLogPrintOrder::LabelAlphabeticAscending {
337                let mut labels_normal: Vec<&Option<&'static str>> = self.labels.iter().collect();
338                labels_normal.sort();
339                let mut logged_blocks_label_sorted: Vec<&HBlockPreformance> = self.log.iter().collect();
340                for (a, b) in zip(logged_blocks_label_sorted, labels_normal) {
341                    a.label = *b;
342                }
343                let new_indecies: Vec<usize> = self.find_new_indecies(HBlockPreformanceField::Label, &logged_blocks, &logged_blocks_label_sorted);       
344                
345                ordered_blocks = self.ordered_list(new_indecies, &logged_blocks);
346            }
347
348            for i in ordered_blocks {
349                i.print_fields_specified(fields_included);
350            }
351        }
352    }
353    
354}
355    
356
357#[macro_export]
358macro_rules! h_block_preformance_log {
359    ($logger_struct:expr, $code:block) => {
360        {
361            if cfg!(debug_assertions) {
362                let start = std::time::Instant::now();
363                $code
364                $logger_struct.push(HBlockPreformance::set_new(None, start.elapsed(), line!(), file!()))
365            } 
366        }
367    };
368}
369
370*/
371#[cfg(test)]
372mod tests {
373    use super::*;
374    use std::collections::HashMap;
375
376    #[test]
377    fn test_hashmap_values_to_hashset() {
378        let mut map = HashMap::new();
379        map.insert(1, "a");
380        map.insert(2, "b");
381        map.insert(3, "a");
382        let set = map.h_hashmap_values_to_hashset();
383        assert_eq!(set.len(), 2);
384        assert!(set.contains("a"));
385        assert!(set.contains("b"));
386    }
387
388    #[test]
389    fn test_hashmap_keys_to_hashset() {
390        let mut map = HashMap::new();
391        map.insert(1, "a");
392        map.insert(2, "b");
393        map.insert(3, "a");
394        let set = map.h_hashmap_keys_to_hashset();
395        assert_eq!(set.len(), 3);
396        assert!(set.contains(&1));
397        assert!(set.contains(&2));
398        assert!(set.contains(&3));
399    }
400
401    #[test]
402    fn test_h_list_to_hashmap() {
403        let keys = vec![1, 2, 3];
404        let values = vec!["a", "b", "c"];
405        let map = h_list_to_hashmap(&keys, &values).unwrap();
406        assert_eq!(map.get(&1), Some(&"a"));
407        assert_eq!(map.get(&2), Some(&"b"));
408        assert_eq!(map.get(&3), Some(&"c"));
409    }
410
411    #[test]
412    fn test_h_list_to_hashmap_length_mismatch() {
413        let keys = vec![1, 2];
414        let values = vec!["a", "b", "c"];
415        let result = h_list_to_hashmap(&keys, &values);
416        assert!(result.is_err());
417    }
418
419    #[test]
420    fn test_h_list_to_hashmap_duplicate_keys() {
421        let keys = vec![1, 1, 2];
422        let values = vec!["a", "b", "c"];
423        let result = h_list_to_hashmap(&keys, &values);
424        assert!(result.is_err());
425    }
426
427    #[test]
428    fn test_list_to_hashset() {
429        let list = vec!["a", "b", "a", "c"];
430        let (set, dupes) = list.h_list_to_hashset();
431        assert_eq!(set.len(), 3);
432        assert!(set.contains("a"));
433        assert!(set.contains("b"));
434        assert!(set.contains("c"));
435        assert_eq!(dupes, 1);
436    }
437}
438
439
440