use std::collections::HashMap;
use std::hash::Hash;
use std::iter::FusedIterator;
pub struct SparseVec<T> {
items: Vec<Option<T>>,
item_locs: HashMap<T, Vec<usize>>,
}
impl<T> Default for SparseVec<T> {
fn default() -> Self {
SparseVec {
items: Vec::default(),
item_locs: HashMap::default(),
}
}
}
impl<T: Clone + Eq + Hash> SparseVec<T> {
pub fn push(&mut self, item: T) {
self.items.push(Some(item.clone()));
self.item_locs
.entry(item)
.or_insert(Vec::with_capacity(1))
.push(self.items.len() - 1);
}
pub fn delete(&mut self, item: &T) {
if let Some(indices) = self.item_locs.get(item) {
for index in indices {
self.items[*index] = None;
}
}
}
pub fn iter(&self) -> impl DoubleEndedIterator<Item = &T> + FusedIterator + Clone {
self.items.iter().filter_map(|x| x.as_ref())
}
}
#[cfg(test)]
mod test {
use super::*;
fn collect<T: Eq + Hash + Clone>(sv: &SparseVec<T>) -> Vec<T> {
sv.iter().cloned().collect()
}
#[test]
fn basic() {
let mut x = SparseVec::default();
x.push(0);
x.push(1);
x.push(2);
x.delete(&1);
assert_eq!(collect(&x), vec![0, 2]);
}
#[test]
fn can_implement_default_on_types_that_dont_implement_default() {
struct NoDefault;
let x = SparseVec::<NoDefault>::default();
assert_eq!(x.items.len(), 0);
assert_eq!(x.item_locs.len(), 0);
}
}