Advertisement
Revolucent

Rust grouping shizz

Nov 20th, 2021
1,856
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Rust 3.02 KB | None | 0 0
  1. // A bit better than my previous attempts
  2.  
  3. mod group {
  4.   use core::slice::Iter;
  5.   use std::hash::Hash;
  6.   use std::collections::HashMap;
  7.  
  8.   pub struct GroupByIter<'a, E: 'a, G: Eq + 'a> {
  9.    iter: Iter<'a, E>,
  10.     test: Box<dyn Fn(&'a E) -> G>,
  11.    curr: Option<G>,
  12.    last: Option<&'a E>
  13.   }
  14.  
  15.   impl<'a, E: 'a, G: Eq + 'a> GroupByIter<'a, E, G> {
  16.     fn new<F: 'static>(slice: &'a [E], test: F) -> GroupByIter<'a, E, G> where F: Fn(&'a E) -> G {
  17.       GroupByIter { iter: slice.iter(), test: Box::new(test), curr: None, last: None }
  18.     }
  19.   }
  20.  
  21.   impl<'a, E: 'a, G: Eq + 'a> Iterator for GroupByIter<'a, E, G> {
  22.     type Item = Vec<&'a E>;
  23.  
  24.    fn next(&mut self) -> Option<Self::Item> {
  25.      let mut group = Vec::new();
  26.      if let Some(e) = self.last {
  27.        group.push(e);
  28.        self.last = None;
  29.      }
  30.      let test = &self.test;
  31.      loop {
  32.        match self.iter.next() {
  33.          None => break,
  34.          Some(e) => {
  35.            let new = Some(test(e));
  36.            if self.curr == new || self.curr.is_none() {
  37.              group.push(e);
  38.              self.curr = new;
  39.            } else {
  40.              self.last = Some(e);
  41.              self.curr = new;
  42.              break;
  43.            }
  44.          }
  45.        }
  46.      }
  47.      if !group.is_empty() { Some(group) } else { None }
  48.    }
  49.  }
  50.  
  51.  pub trait Groupable {
  52.    type Item;
  53.  
  54.    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;
  55.  
  56.    fn group<'a>(&'a self) -> GroupByIter<'a, Self::Item, &'a Self::Item> where Self::Item: Eq + 'a {
  57.       self.group_by(|e| e)
  58.     }
  59.  
  60.     fn categorize_by<'a, F: 'static, G: Eq + Hash + 'a>(&'a self, test: F) -> HashMap<G, Vec<&'a Self::Item>> where F: Fn(&'a Self::Item) -> G;
  61.  
  62.     fn counts_by<'a, F: 'static, C: Eq + Hash + 'a>(&'a self, test: F) -> HashMap<C, usize> where F: Fn(&'a Self::Item) -> C {
  63.      self.categorize_by(test).into_iter().map(|g| (g.0, g.1.len())).collect()
  64.    }
  65.  
  66.    fn counts<'a>(&'a self) -> HashMap<&'a Self::Item, usize> where Self::Item: Eq + Hash {
  67.       self.counts_by(|e| e)
  68.     }
  69.   }
  70.  
  71.   impl<E> Groupable for [E] {
  72.     type Item = E;
  73.  
  74.     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 {
  75.      GroupByIter::new(self, test)
  76.    }
  77.  
  78.    fn categorize_by<'a, F: 'static, G: Eq + Hash + 'a>(&'a self, test: F) -> HashMap<G, Vec<&'a Self::Item>> where F: Fn(&'a Self::Item) -> G {
  79.      let mut map: HashMap<G, Vec<&Self::Item>> = HashMap::new();
  80.      for e in self {
  81.        map.entry(test(e))
  82.          .and_modify(|g| g.push(e))
  83.          .or_insert(vec![e]);
  84.      }
  85.      map
  86.    }
  87.  
  88.    fn counts_by<'a, F: 'static, C: Eq + Hash + 'a>(&'a self, test: F) -> HashMap<C, usize> where F: Fn(&'a Self::Item) -> C {
  89.       let mut map = HashMap::new();
  90.       for e in self {
  91.         let c = test(&e);
  92.         map.entry(c)
  93.           .and_modify(|e| *e += 1)
  94.           .or_insert(1);
  95.       }
  96.       map
  97.     }
  98.   }
  99. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement