ai_utils/
ranges.rs

1use std::{collections::HashMap, hash::Hash, ops::Deref};
2
3pub trait ToVec: Iterator {
4    fn to_vec(self) -> Vec<Self::Item>;
5}
6
7impl<I> ToVec for I
8where
9    I: Iterator,
10{
11    fn to_vec(self) -> Vec<Self::Item> {
12        let mut result = vec![];
13        for i in self {
14            result.push(i);
15        }
16        result
17    }
18}
19
20pub trait Distinct: Iterator {
21    fn distinct(self) -> Vec<Self::Item>;
22}
23
24impl<I: Iterator> Distinct for I
25where
26    I::Item: PartialEq,
27{
28    fn distinct(self) -> Vec<Self::Item> {
29        let mut tmp: Vec<Self::Item> = vec![];
30        for i in self {
31            if !tmp.contains(&i) {
32                tmp.push(i);
33            }
34        }
35        tmp
36    }
37}
38
39pub trait GroupBy: Iterator {
40    fn group_by<T: Hash + Eq, U: Fn(&Self::Item) -> T>(
41        self,
42        get_key: U,
43    ) -> HashMap<T, Vec<Self::Item>>;
44}
45
46impl<I: Iterator> GroupBy for I {
47    fn group_by<T: Hash + Eq, U: Fn(&Self::Item) -> T>(
48        self,
49        get_key: U,
50    ) -> HashMap<T, Vec<Self::Item>> {
51        let mut dict = HashMap::new();
52        for v in self {
53            let k = get_key(&v);
54            match dict.get_mut(&k) {
55                None => {
56                    let mut list = vec![];
57                    list.push(v);
58                    dict.insert(k, list);
59                }
60                Some(list) => list.push(v),
61            }
62        }
63        dict
64    }
65}
66
67pub trait GroupByAggrCopy: Iterator {
68    fn group_by_aggr<
69        T: Hash + Eq + Deref + Copy,
70        K: Fn(&Self::Item) -> T,
71        R,
72        A: Fn(&Vec<Self::Item>) -> R,
73    >(
74        self,
75        get_key: K,
76        aggrs: HashMap<&str, A>,
77    ) -> HashMap<T, HashMap<&str, R>>;
78}
79
80impl<I: Iterator> GroupByAggrCopy for I {
81    fn group_by_aggr<
82        T: Hash + Eq + Deref + Copy,
83        K: Fn(&Self::Item) -> T,
84        R,
85        A: Fn(&Vec<Self::Item>) -> R,
86    >(
87        self,
88        get_key: K,
89        aggrs: HashMap<&str, A>,
90    ) -> HashMap<T, HashMap<&str, R>> {
91        let mut tmp_dict = HashMap::new();
92        for v in self {
93            let k = get_key(&v);
94            match tmp_dict.get_mut(&k) {
95                None => {
96                    let mut list = vec![];
97                    list.push(v);
98                    tmp_dict.insert(k, list);
99                }
100                Some(list) => list.push(v),
101            }
102        }
103        let mut dict: HashMap<T, HashMap<&str, R>> = HashMap::new();
104        for (k1, v1) in tmp_dict.iter() {
105            let mut sub_dict = HashMap::new();
106            for (k2, aggr) in aggrs.iter() {
107                let res_aggr = aggr(v1);
108                sub_dict.insert(*k2, res_aggr);
109            }
110            dict.insert(*k1, sub_dict);
111        }
112        dict
113    }
114}
115
116pub trait GroupByAggrClone: Iterator {
117    fn group_by_aggr_clone<
118        T: Hash + Eq + Clone,
119        K: Fn(&Self::Item) -> T,
120        R,
121        A: Fn(&Vec<Self::Item>) -> R,
122    >(
123        self,
124        get_key: K,
125        aggrs: HashMap<&str, A>,
126    ) -> HashMap<T, HashMap<&str, R>>;
127}
128
129impl<I: Iterator> GroupByAggrClone for I {
130    fn group_by_aggr_clone<
131        T: Hash + Eq + Clone,
132        K: Fn(&Self::Item) -> T,
133        R,
134        A: Fn(&Vec<Self::Item>) -> R,
135    >(
136        self,
137        get_key: K,
138        aggrs: HashMap<&str, A>,
139    ) -> HashMap<T, HashMap<&str, R>> {
140        let mut tmp_dict = HashMap::new();
141        for v in self {
142            let k = get_key(&v);
143            match tmp_dict.get_mut(&k) {
144                None => {
145                    let mut list = vec![];
146                    list.push(v);
147                    tmp_dict.insert(k, list);
148                }
149                Some(list) => list.push(v),
150            }
151        }
152        let mut dict: HashMap<T, HashMap<&str, R>> = HashMap::new();
153        for (k1, v1) in tmp_dict.iter() {
154            let mut sub_dict = HashMap::new();
155            for (k2, aggr) in aggrs.iter() {
156                let res_aggr = aggr(v1);
157                sub_dict.insert(*k2, res_aggr);
158            }
159            dict.insert(k1.clone(), sub_dict);
160        }
161        dict
162    }
163}
164
165#[cfg(test)]
166mod ranges_tests {
167    use super::*;
168
169    #[test]
170    fn to_vec() {
171        let jarak = (0..100).filter(|i| i % 2 == 0).to_vec();
172        println!("Result : {:?}", jarak);
173    }
174
175    #[test]
176    fn distinct() {
177        let result = (0..100).map(|x| x % 3).distinct();
178        println!("Result : {:?}", result);
179    }
180
181    #[derive(Debug)]
182    struct Grouped {
183        cat: &'static str,
184        val: i32,
185    }
186
187    impl std::fmt::Display for Grouped {
188        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
189            write!(f, "Grouped[cat={}, val={}]", self.cat, self.val)
190        }
191    }
192
193    #[test]
194    fn group_by() {
195        let result = (0..10)
196            .map(|i| Grouped {
197                cat: if i % 2 == 0 { "Genap" } else { "Ganjil" },
198                val: i,
199            })
200            .group_by(|g| g.cat);
201        println!("Result : {:?}", result)
202    }
203
204    type Aggr = fn(&Vec<Grouped>) -> usize;
205
206    #[test]
207    fn group_by_aggr() {
208        let mut aggrs: HashMap<&str, Aggr> = HashMap::new();
209        aggrs.insert("sum", |a: &Vec<Grouped>| {
210            a.iter()
211                .map(|g| {
212                    let i: usize = g.val.try_into().unwrap();
213                    i
214                })
215                .sum::<usize>()
216        });
217        aggrs.insert("avg", |a: &Vec<Grouped>| {
218            let sum = a
219                .iter()
220                .map(|g| {
221                    let i: usize = g.val.try_into().unwrap();
222                    i
223                })
224                .sum::<usize>();
225            sum / a.len()
226        });
227        aggrs.insert("product", |a: &Vec<Grouped>| {
228            a.iter()
229                .map(|g| {
230                    let i: usize = g.val.try_into().unwrap();
231                    i
232                })
233                .product::<usize>()
234        });
235        aggrs.insert("max", |a: &Vec<Grouped>| {
236            a.iter()
237                .map(|g| {
238                    let i: usize = g.val.try_into().unwrap();
239                    i
240                })
241                .max()
242                .unwrap()
243        });
244        aggrs.insert("min", |a: &Vec<Grouped>| {
245            a.iter()
246                .map(|g| {
247                    let i: usize = g.val.try_into().unwrap();
248                    i
249                })
250                .min()
251                .unwrap()
252        });
253        aggrs.insert("len", |a| a.len());
254        let result = (1..=20)
255            .map(|i| Grouped {
256                cat: if i % 3 == 0 {
257                    "Tiga"
258                } else if i % 3 == 2 {
259                    "Dua"
260                } else {
261                    "Satu"
262                },
263                val: i,
264            })
265            .group_by_aggr(|g| g.cat, aggrs);
266        println!("Result : {:?}", result)
267    }
268}