Revolucent icon

Rust grouping/counting stuff

Revolucent | PRO | 11/20/21 01:36:11 AM UTC | 0 ⭐ | 9301 👁️ | Never ⏰ | []
Rust |

2.19 KB

|

None

|

0 👍

/

0 👎

// Just some code the help learn Rust, traits, lifetimes, etc.
 
mod group {
  use core::slice::Iter;
  use std::collections::HashMap;
  use std::hash::Hash;
 
  pub struct GroupByIter<'a, E: 'a, F: 'a, G: Eq + 'a> where F: Fn(&'a E) -> G {
    iter: Iter<'a, E>,
    test: Box<F>,
    curr: Option<G>,
    last: Option<&'a E>
  } 
 
  impl<'a, E: 'a, F: 'a, G: Eq + 'a> GroupByIter<'a, E, F, G> where F: Fn(&'a E) -> G {
    fn new(slice: &'a [E], test: F) -> GroupByIter<'a, E, F, G> {
      GroupByIter { iter: slice.iter(), test: Box::new(test), curr: None, last: None }
    }
  }
 
  pub trait GroupBy {
    type Item;
 
    fn group_by<'a, F: 'a, G: Eq + 'a>(&'a self, test: F) -> GroupByIter<'a, Self::Item, F, G> where Self::Item: 'a, F: Fn(&'a Self::Item) -> G;
  }
 
  impl<E> GroupBy for [E] {
    type Item = E;
 
    fn group_by<'a, F: 'a, G: Eq + 'a>(&'a self, test: F) -> GroupByIter<'a, E, F, G> where E: 'a, F: Fn(&'a E) -> G {
      GroupByIter::new(self, test)
    }
  }
 
  impl<'a, E: 'a, F: 'a, G: Eq + 'a> Iterator for GroupByIter<'a, E, F, G> where F: Fn(&'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 Countable {
    type Item: Eq + Hash;
    
    fn counts<'a>(&'a self) -> HashMap<&'a Self::Item, usize>;
  }
 
  impl<E: Eq + Hash> Countable for [E] {
    type Item = E;
 
    fn counts<'a>(&'a self) -> HashMap<&'a E, usize> {
      let mut map = HashMap::new();
      for e in self {
        map.insert(e, map.get(e).unwrap_or(&0) + 1);
      }
      map
    }
  }
}

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

    |

    👍

    /

    👎