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}