more_itertools/augmenting/
groupby_transform.rs

1use 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                        // funced_cur_key != funced_key
69                        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}