1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
use std::cmp::Ordering::{Greater, Equal, Less}; pub struct Slide<T: Iterator<Item=A>, A> { iter: T, n: usize, window: Vec<A> } macro_rules! return_if( ($cond:expr, $value:expr) => ( if $cond { return $value; } ); ); impl<A: Clone, T: Iterator<Item=A>> Slide<T, A> { fn push_window(&mut self) -> bool { let iter_next = self.iter.next(); let is_some = iter_next.is_some(); if is_some { self.window.push(iter_next.unwrap()); } is_some } fn new(iter: T, n: usize) -> Slide<T, A> { Slide{ iter: iter, n: n, window: Vec::with_capacity(n + 1) } } } impl<A: Clone, T: Iterator<Item=A>> Iterator for Slide<T, A> { type Item = Vec<A>; fn next(&mut self) -> Option<Vec<A>> { return_if!(self.n == 0, None); return_if!(!self.push_window(), None); loop { let window_status = self.window.len().cmp(&self.n); match window_status { Greater => { self.window.remove(0); } Equal => { return Some(self.window.clone()); } Less => { return_if!(!self.push_window(), None); } } } } } pub trait SlideIterator<T: Iterator<Item=A>, A> { fn slide(self, n: usize) -> Slide<T, A>; } impl<A: Clone, T: Iterator<Item=A>> SlideIterator<T, A> for T { fn slide(self, n: usize) -> Slide<T, A> { Slide::new(self, n) } } #[test] fn test_slide() { let mut slide_iter = vec![1i8, 2, 3, 4, 5].into_iter().slide(3); assert_eq!(slide_iter.next().unwrap(), vec![1, 2, 3]); assert_eq!(slide_iter.next().unwrap(), vec![2, 3, 4]); assert_eq!(slide_iter.next().unwrap(), vec![3, 4, 5]); assert!(slide_iter.next().is_none()); } #[test] fn test_slide_equal_window() { let mut slide_iter = vec![1i8, 2, 3, 4, 5].into_iter().slide(5); assert_eq!(slide_iter.next().unwrap(), vec![1, 2, 3, 4, 5]); assert!(slide_iter.next().is_none()); } #[test] fn test_slide_zero_window() { let mut slide_iter = vec![1i8, 2, 3, 4, 5].into_iter().slide(0); assert!(slide_iter.next().is_none()); } #[test] fn test_slide_overlong_window() { let mut slide_iter = vec![1i8, 2, 3, 4, 5].into_iter().slide(7); assert!(slide_iter.next().is_none()); }