more_itertools/augmenting/
groupby_transform.rs1use std::collections::VecDeque;
2use std::fmt::Debug;
3use crate::utils::are_same;
4
5pub struct GroupByTransform<T, TKey, TValue, TReduce>
6where T: Clone + Debug + PartialEq,
7{
8 key_buf: VecDeque<TKey>,
9 funced_cur_key: Option<TKey>,
10 value_buf: Vec<TValue>,
11 input_buf: VecDeque<T>,
12 iter: Box<dyn Iterator<Item = T>>,
13 iter_finished: bool,
14
15
16 keyfunc: fn(&T)->TKey,
17 valuefunc: fn(&T)->TValue,
18 reducefunc: fn(&Vec<TValue>)-> TReduce
19}
20
21
22impl<T, TKey, TValue, TReduce> Iterator for GroupByTransform<T, TKey, TValue, TReduce>
23where
24T: PartialEq + Clone + Debug,
25TKey: PartialEq + Clone + Debug
26{
27 type Item = (TKey, TReduce);
28
29 fn next(&mut self) -> Option<Self::Item> {
30 loop {
31 if self.iter_finished && self.value_buf.len() == 0 {
32 return None;
33 }
34
35 if self.value_buf.len() > 0 {
36 let funced_cur_key = self.key_buf.pop_front();
37 let reduce_result = (self.reducefunc)(&self.value_buf);
38 self.value_buf = Vec::new();
39 return Some((funced_cur_key.as_ref().unwrap().clone(), reduce_result))
40 }
41
42 loop {
43 let _next = self.iter.next();
44 match _next {
45 None => {
46 self.iter_finished = true;
47 },
48 Some(v) => {
49 self.input_buf.push_back(v);
50 }
51 }
52
53 if self.input_buf.len() == 0 {
54 break;
55 }
56
57 let v = self.input_buf.front().unwrap().clone();
58
59 let funced_key = (self.keyfunc)(&v);
60
61 let funced_value = (self.valuefunc)(&v);
62
63 if !self.funced_cur_key.is_none() {
64 if are_same(Some(self.funced_cur_key.as_ref().unwrap()), Some(&funced_key)) {
65 self.value_buf.push(funced_value);
66 self.input_buf.pop_front();
67 } else {
68 self.funced_cur_key = Some(funced_key);
70 self.key_buf.push_back(self.funced_cur_key.as_ref().unwrap().clone());
71 break;
72 }
73 } else {
74 self.funced_cur_key = Some((self.keyfunc)(&v));
75 self.key_buf.push_back(self.funced_cur_key.as_ref().unwrap().clone());
76 println!("====>{:?}", self.funced_cur_key);
77 break;
78 }
79 }
80 }
81 }
82}
83
84pub fn groupby_transform<T, TKey, TValue, TReduce>(iter: Box<dyn Iterator<Item = T>>,
85 keyfunc: fn(&T)->TKey,
86 valuefunc: fn(&T)->TValue,
87 reducefunc: fn(&Vec<TValue>)-> TReduce
88 ) -> GroupByTransform<T, TKey, TValue, TReduce>
89where
90T: PartialEq + Clone + Debug
91{
92 return GroupByTransform {
93 key_buf: VecDeque::new(),
94 funced_cur_key: None,
95 value_buf: Vec::new(),
96 input_buf: VecDeque::new(),
97 iter,
98 iter_finished: false,
99
100 keyfunc,
101 valuefunc,
102 reducefunc,
103 }
104}
105
106#[cfg(test)]
107mod tests {
108 use crate::itertools::iter::iter_from_vec;
109
110 use super::*;
111
112 #[test]
113 fn test1() {
114 let mut ret: GroupByTransform<char, char, char, String> = groupby_transform(iter_from_vec("aAAAbbbcccC".chars().collect::<Vec<char>>()),
115 |x| {x.to_ascii_uppercase()},
116 |x| { *x },
117 |x| { return String::from_iter(x); }
118 );
119
120 assert_eq!(Some(('A', "aAAA".to_string())), ret.next());
121 assert_eq!(Some(('B', "bbb".to_string())), ret.next());
122 assert_eq!(Some(('C', "cccC".to_string())), ret.next());
123 assert_eq!(None, ret.next());
124 assert_eq!(None, ret.next());
125 }
126
127 #[test]
128 fn test2() {
129 let mut ret: GroupByTransform<char, char, char, String> = groupby_transform(iter_from_vec("aAAAbbbcccC".chars().collect::<Vec<char>>()),
130 |x| {x.to_ascii_uppercase()},
131 |x| { x.to_ascii_lowercase() },
132 |x| { return String::from_iter(x); }
133 );
134
135 assert_eq!(Some(('A', "aaaa".to_string())), ret.next());
136 assert_eq!(Some(('B', "bbb".to_string())), ret.next());
137 assert_eq!(Some(('C', "cccc".to_string())), ret.next());
138 assert_eq!(None, ret.next());
139 assert_eq!(None, ret.next());
140 }
141}