Revolucent icon

Rust grouping constructs

Revolucent | PRO | 11/20/21 02:53:12 AM UTC | 0 ⭐ | 8831 👁️ | Never ⏰ | []
Rust |

1.87 KB

|

None

|

0 👍

/

0 👎

// 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<dyn Fn(&'a E) -> G>,
    curr: Option<G>,
    last: Option<&'a E>
  } 
 
  impl<'a, E: 'a, G: Eq + 'a> GroupByIter<'a, E, G> {
    fn new<F: 'static>(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<Self::Item> {
      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<E> 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)
    }
  }
}

Comments

  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎

    
        
  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎