// Better grouping in Rust. My first attempt leaked the type of the test function which made reuse harder. mod group { use core::slice::Iter; pub struct GroupByIter<'a, E: 'a, G: Eq + 'a> { iter: Iter<'a, E>, test: Box G>, curr: Option, last: Option<&'a E> } impl<'a, E: 'a, G: Eq + 'a> GroupByIter<'a, E, G> { fn new(slice: &'a [E], test: F) -> GroupByIter<'a, E, G> where F: Fn(&'a E) -> G { GroupByIter { iter: slice.iter(), test: Box::new(test), curr: None, last: None } } } impl<'a, E: 'a, G: Eq + 'a> Iterator for GroupByIter<'a, E, G> { type Item = Vec<&'a E>; fn next(&mut self) -> Option { let mut group = Vec::new(); if let Some(e) = self.last { group.push(e); self.last = None; } let test = &self.test; loop { match self.iter.next() { None => break, Some(e) => { let new = Some(test(e)); if self.curr == new || self.curr.is_none() { group.push(e); self.curr = new; } else { self.last = Some(e); self.curr = new; break; } } } } if !group.is_empty() { Some(group) } else { None } } } pub trait GroupBy { type Item; fn group_by<'a, F: 'static, G: Eq + 'a>(&'a self, test: F) -> GroupByIter<'a, Self::Item, G> where F: Fn(&'a Self::Item) -> G; fn group<'a>(&'a self) -> GroupByIter<'a, Self::Item, &'a Self::Item> where Self::Item: Eq + 'a { self.group_by(|e| e) } } impl GroupBy for [E] { type Item = E; fn group_by<'a, F: 'static, G: Eq + 'a>(&'a self, test: F) -> GroupByIter<'a, E, G> where E: 'a, F: Fn(&'a E) -> G { GroupByIter::new(self, test) } } }