1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
//! # elements frequency //! //! Finds frequency table of the unique elements present in the list. //! In the table the elements come in "First come first serve" manner, //! namingly the order they appear in the list. //! //! This lbrary can work with any types that implement `Clone`. //! So it is expected to work with Strings, slices, integers etc. //! //! ### Quick Example //! ``` //! use elements_frequency::{Row, Elements}; //! //! let list = vec!["hi", "who", "me", "who", "me"]; //! //! let mut elements = Elements::new(&list); //! //! let frequency_table = elements //! .hash_couple() //! .update_order() //! .result(); //! //! println!("{:?}", frequency_table); //! //! // //! // [ //! // Row { element: "hi", frequency: 1 }, //! // Row { element: "who", frequency: 2 }, //! // Row { element: "me", frequency: 2 }, //! // ] //! // //! ``` use std::{collections::HashMap, hash::Hash}; /// This struct acts like rows in frequency table, and holds 2 fields, /// the element and its frequency. #[derive(Debug, PartialEq)] pub struct Row<U> { pub element: U, pub frequency: u32, } impl<U> Row<U> { /// Returns an instance of `Row` struct. pub fn new(element: U, frequency: u32) -> Self { Row { element, frequency } } } /// This struct holds 3 fields:\ /// 1.`list`: The list itself\ /// \ /// 2. `couple_hash`: Elements hashed to their frequency. /// they may come unordered when iterated over.\ /// \ /// 3. `ordered_table`: This field holds the ordered frequency table. #[derive(Debug)] pub struct Elements<'list, T> { list: &'list Vec<T>, couple_hash: HashMap<T, u32>, ordered_table: Vec<Row<T>>, } impl<'list, T> Elements<'list, T> where T: Clone + Hash + Eq, { /// Returns a new instance of the struct. pub fn new(list: &'list Vec<T>) -> Self { Elements { list, couple_hash: HashMap::new(), ordered_table: Vec::new(), } } /// Hash the elements to its frequency. pub fn hash_couple(&mut self) -> &mut Self { let list: &Vec<T> = self.list; let couple_hash: &mut HashMap<T, u32> = &mut self.couple_hash; let ordered_table: &mut Vec<Row<T>> = &mut self.ordered_table; for i in list { match couple_hash.get_mut(i) { Some(val) => { *val += 1; } None => { couple_hash.insert((*i).clone(), 1); ordered_table.push(Row::new((*i).clone(), 0)) } } } self } /// When we iterate over the hash, the elements might come unordered. /// So we update their order in this method in a third list namingly /// frequency table. pub fn update_order(&mut self) -> &Self { let couple_hash: &mut HashMap<T, u32> = &mut self.couple_hash; let ordered_table: &mut Vec<Row<T>> = &mut self.ordered_table; for row in ordered_table.iter_mut() { let val: &u32 = couple_hash.get(&row.element).unwrap(); row.frequency += *val; } self } /// Finally we need to chain `hash_couple` and `update_order` with /// `result` method to get final result. /// /// # Examples /// ``` /// use elements_frequency::{Row, Elements}; /// /// let list = vec![-5, 11, 4, 4, -5, -7, 11]; /// /// let mut elements = Elements::new(&list); /// /// let frequency_table = elements.hash_couple().update_order().result(); /// ``` pub fn result(&self) -> &Vec<Row<T>> { let ordered_table: &Vec<Row<T>> = &self.ordered_table; ordered_table } }