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
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 }
    }
}

#[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 their 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::interface::{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
    }
}