.dedup() on iterators
| use std::iter::Peekable; | |
| trait IteratorDedup: Iterator + Sized { | |
| fn dedup(self) -> Dedup<Self> where Self::Item: PartialEq { | |
| Dedup { | |
| inner: self.peekable(), | |
| emit: true, | |
| } | |
| } | |
| } | |
| impl<I> IteratorDedup for I where I: Iterator + Sized {} | |
| struct Dedup<I: Iterator> { | |
| inner: Peekable<I>, | |
| emit: bool, | |
| } | |
| impl<I> Iterator for Dedup<I> where I: Iterator, <I as Iterator>::Item: PartialEq { | |
| type Item = <I as Iterator>::Item; | |
| fn next(&mut self) -> Option<<I as Iterator>::Item> { | |
| let result = | |
| if self.emit { | |
| self.inner.next() | |
| } else { | |
| let first = match self.inner.next() { | |
| None => return None, | |
| Some(first) => first, | |
| }; | |
| self.inner.find(|item| first != *item) | |
| }; | |
| self.emit = result.as_ref() != self.inner.peek(); | |
| result | |
| } | |
| } | |
| fn dedup_test<T: PartialEq + Clone>(input: &[T]) -> Vec<T> { | |
| input.iter().cloned().dedup().collect() | |
| } | |
| #[test] | |
| fn smoke_test() { | |
| assert_eq!(dedup_test::<i32>(&[]), []); | |
| assert_eq!(dedup_test(&[1]), [1]); | |
| assert_eq!(dedup_test(&[1, 2, 3]), [1, 2, 3]); | |
| assert_eq!(dedup_test(&[1, 1, 2, 3]), [1, 2, 3]); | |
| assert_eq!(dedup_test(&[1, 2, 2, 3, 3]), [1, 2, 3]); | |
| assert_eq!(dedup_test(&[1, 2, 2, 2, 3]), [1, 2, 3]); | |
| assert_eq!(dedup_test(&[1, 1, 1, 1, 1]), [1]); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment