use std::collections::HashMap;
pub(crate) struct OrderedVecMap<K, V> {
map: HashMap<K, Vec<V>>,
keys: Vec<K>,
}
impl<K, V> OrderedVecMap<K, V> {
pub fn new() -> Self {
Self {
map: HashMap::new(),
keys: Vec::new(),
}
}
pub fn into_iter(self) -> IntoIter<K, V> {
IntoIter { map: self }
}
pub fn insert_push(&mut self, key: K, item: V)
where
K: Eq + std::hash::Hash + Clone,
{
let entry = self.map.entry(key.clone()).or_default();
if entry.is_empty() {
self.keys.push(key);
}
entry.push(item);
}
}
impl<K, V> IntoIterator for OrderedVecMap<K, V>
where
K: Eq + std::hash::Hash,
{
type Item = (K, Vec<V>);
type IntoIter = IntoIter<K, V>;
fn into_iter(self) -> Self::IntoIter {
IntoIter { map: self }
}
}
pub struct IntoIter<K, V> {
map: OrderedVecMap<K, V>,
}
impl<K, V> Iterator for IntoIter<K, V>
where
K: Eq + std::hash::Hash,
{
type Item = (K, Vec<V>);
fn next(&mut self) -> Option<Self::Item> {
if self.map.keys.is_empty() {
return None;
}
let key = self.map.keys.remove(0);
let value = self.map.map.remove(&key).expect("guaranteed key exists");
Some((key, value))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_ordered_map() {
let mut map = OrderedVecMap::new();
map.insert_push(1, 1);
map.insert_push(1, 2);
map.insert_push(2, 3);
map.insert_push(2, 4);
map.insert_push(3, 5);
map.insert_push(3, 6);
let mut iter = map.into_iter();
assert_eq!(iter.next(), Some((1, vec![1, 2])));
assert_eq!(iter.next(), Some((2, vec![3, 4])));
assert_eq!(iter.next(), Some((3, vec![5, 6])));
assert_eq!(iter.next(), None);
}
#[test]
fn into_iter() {
let mut map = OrderedVecMap::new();
map.insert_push(1, 1);
map.insert_push(1, 2);
map.insert_push(2, 3);
map.insert_push(2, 4);
map.insert_push(3, 5);
map.insert_push(3, 6);
for (key, value) in map {
println!("{:?} {:?}", key, value);
}
}
}