more_itertools/grouping/
partition.rs

1use std::rc::Rc;
2
3use crate::sequence::Sequence;
4
5
6pub struct PartitionInner<T> {
7    buf: Box<dyn Sequence<T>>,
8    pred: fn(&T) -> bool
9}
10
11pub struct Partition<T> {
12    inner: Rc<PartitionInner<T>>
13}
14
15pub struct CursorFalse<T> {
16    inner: Rc<PartitionInner<T>>,
17    _next: usize
18}
19
20pub struct CursorTrue<T> {
21    inner: Rc<PartitionInner<T>>,
22    _next: usize
23}
24
25impl<T> Iterator for CursorFalse<T>
26where
27T: Clone
28{
29    type Item = T;
30
31    fn next(&mut self) -> Option<Self::Item> {
32        loop {
33            if self._next >= self.inner.buf.len() {
34                return None;
35            }
36            let t = self.inner.buf.get(self._next).unwrap();
37            self._next += 1;
38            if !(self.inner.pred)(t) {
39                return Some(t.clone());
40            }
41        }
42    }
43}
44
45impl<T> Iterator for CursorTrue<T>
46where
47T: Clone
48{
49    type Item = T;
50
51    fn next(&mut self) -> Option<Self::Item> {
52        loop {
53            if self._next >= self.inner.buf.len() {
54                return None;
55            }
56            let t = self.inner.buf.get(self._next).unwrap();
57            self._next += 1;
58            if (self.inner.pred)(t) {
59                return Some(t.clone());
60            }
61        }
62    }
63}
64
65impl<T> Partition<T> 
66where T: Clone + 'static
67{
68    pub fn new(buf: Box<dyn Sequence<T>>, pred: fn(&T) -> bool) -> Partition<T> {
69        let inner = PartitionInner {
70            buf: buf,
71            pred: pred
72        };
73
74        let ret = Partition {
75            inner: Rc::new(inner)
76        };
77
78        return ret;
79    }
80
81    pub fn get_cursor(&self) -> (Box<dyn Iterator<Item = T>>, Box<dyn Iterator<Item = T>>){
82        let cur_false: Box<dyn Iterator<Item = T>> = Box::new(CursorFalse {
83            inner: Rc::clone(&self.inner),
84            _next: 0
85        });
86        let cur_true: Box<dyn Iterator<Item = T>> = Box::new(CursorTrue {
87            inner: Rc::clone(&self.inner),
88            _next: 0
89        });
90        return (cur_false, cur_true);
91    }
92}
93
94pub fn partition<T>(buf: Box<dyn Sequence<T>>, pred: fn(&T) -> bool) -> (Box<dyn Iterator<Item = T>>, Box<dyn Iterator<Item = T>>) 
95where T: Clone + 'static
96{
97    let p = Partition::new(buf, pred);
98    return p.get_cursor();
99}
100
101
102#[cfg(test)]
103mod tests {
104    use crate::sequence::create_seq_from_vec;
105
106    use super::*;
107
108    #[test]
109    fn test1() {
110        let v = vec![1,2,3,4,5,6,7,8,9,10];
111
112        let (cur_false, cur_true) = partition(create_seq_from_vec(v), |x| {x % 2 == 1});
113        assert_eq!(vec![2, 4, 6, 8, 10], cur_false.collect::<Vec<_>>());
114        assert_eq!(vec![1, 3, 5, 7, 9], cur_true.collect::<Vec<_>>());
115    }
116}