Advertisement
Revolucent

Rust grouping constructs

Nov 19th, 2021
1,706
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Rust 1.87 KB | None | 0 0
  1. // Better grouping in Rust. My first attempt leaked the type of the test function which made reuse harder.
  2.  
  3. mod group {
  4.   use core::slice::Iter;
  5.  
  6.   pub struct GroupByIter<'a, E: 'a, G: Eq + 'a> {
  7.    iter: Iter<'a, E>,
  8.     test: Box<dyn Fn(&'a E) -> G>,
  9.    curr: Option<G>,
  10.    last: Option<&'a E>
  11.   }
  12.  
  13.   impl<'a, E: 'a, G: Eq + 'a> GroupByIter<'a, E, G> {
  14.     fn new<F: 'static>(slice: &'a [E], test: F) -> GroupByIter<'a, E, G> where F: Fn(&'a E) -> G {
  15.       GroupByIter { iter: slice.iter(), test: Box::new(test), curr: None, last: None }
  16.     }
  17.   }
  18.  
  19.   impl<'a, E: 'a, G: Eq + 'a> Iterator for GroupByIter<'a, E, G> {
  20.     type Item = Vec<&'a E>;
  21.  
  22.    fn next(&mut self) -> Option<Self::Item> {
  23.      let mut group = Vec::new();
  24.      if let Some(e) = self.last {
  25.        group.push(e);
  26.        self.last = None;
  27.      }
  28.      let test = &self.test;
  29.      loop {
  30.        match self.iter.next() {
  31.          None => break,
  32.          Some(e) => {
  33.            let new = Some(test(e));
  34.            if self.curr == new || self.curr.is_none() {
  35.              group.push(e);
  36.              self.curr = new;
  37.            } else {
  38.              self.last = Some(e);
  39.              self.curr = new;
  40.              break;
  41.            }
  42.          }
  43.        }
  44.      }
  45.      if !group.is_empty() { Some(group) } else { None }
  46.    }
  47.  }
  48.  
  49.  pub trait GroupBy {
  50.    type Item;
  51.  
  52.    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;
  53.  
  54.    fn group<'a>(&'a self) -> GroupByIter<'a, Self::Item, &'a Self::Item> where Self::Item: Eq + 'a {
  55.       self.group_by(|e| e)
  56.     }
  57.   }
  58.  
  59.   impl<E> GroupBy for [E] {
  60.     type Item = E;
  61.  
  62.     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 {
  63.      GroupByIter::new(self, test)
  64.    }
  65.  }
  66. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement