#![doc(html_root_url = "https://docs.rs/mset/0.1.0")]
use std::borrow::Borrow;
use std::cmp::min;
use std::collections::hash_map::{self, Entry, RandomState};
use std::collections::HashMap;
use std::fmt;
use std::hash::{BuildHasher, Hash};
use std::iter::{Chain, FromIterator, FusedIterator};
use std::ops;
#[derive(Clone)]
pub struct MultiSet<T, S = RandomState> {
elem_counts: HashMap<T, usize, S>,
}
impl<T> MultiSet<T, RandomState> {
pub fn new() -> MultiSet<T, RandomState> {
MultiSet {
elem_counts: HashMap::new(),
}
}
pub fn with_capacity(capacity: usize) -> MultiSet<T, RandomState> {
MultiSet {
elem_counts: HashMap::with_capacity(capacity),
}
}
}
impl<T, S> MultiSet<T, S> {
pub fn capacity(&self) -> usize {
self.elem_counts.capacity()
}
pub fn element_counts(&self) -> ElementCounts<T> {
ElementCounts {
iter: self.elem_counts.iter(),
}
}
pub fn distinct_elements(&self) -> Elements<T> {
self.elem_counts.keys()
}
pub fn len(&self) -> usize {
self.elem_counts.values().sum()
}
pub fn is_empty(&self) -> bool {
self.elem_counts.is_empty()
}
pub fn clear(&mut self) {
self.elem_counts.clear()
}
}
impl<T: Hash + Eq, S: BuildHasher> MultiSet<T, S> {
pub fn with_hasher(hash_builder: S) -> MultiSet<T, S> {
MultiSet {
elem_counts: HashMap::with_hasher(hash_builder),
}
}
pub fn with_capacity_and_hasher(capacity: usize, hash_builder: S) -> MultiSet<T, S> {
MultiSet {
elem_counts: HashMap::with_capacity_and_hasher(capacity, hash_builder),
}
}
pub fn hasher(&self) -> &S {
self.elem_counts.hasher()
}
pub fn reserve(&mut self, additional: usize) {
self.elem_counts.reserve(additional)
}
pub fn shrink_to_fit(&mut self) {
self.elem_counts.shrink_to_fit();
}
pub fn iter(&self) -> Iter<T> {
Iter {
iter: self.elem_counts.iter(),
}
}
pub fn iter_with_multiplicity(&self) -> impl Iterator<Item = T> + '_
where
T: Clone,
{
self.iter()
.flat_map(|(el, cnt)| std::iter::repeat_with(move || el.clone()).take(*cnt))
}
pub fn is_disjoint(&self, other: &MultiSet<T, S>) -> bool {
match self.len() < other.len() {
true => self.iter().all(|(e, _)| !other.contains(e)),
false => other.iter().all(|(e, _)| !self.contains(e)),
}
}
pub fn is_subset(&self, other: &MultiSet<T, S>) -> bool {
self.iter()
.all(|(e, m)| *m <= other.get(e).unwrap_or_default())
}
pub fn is_superset(&self, other: &MultiSet<T, S>) -> bool {
other.is_subset(self)
}
pub fn insert(&mut self, value: T) -> bool {
self.insert_times(value, 1)
}
pub fn insert_times(&mut self, value: T, multiplicity: usize) -> bool {
match self.elem_counts.entry(value) {
Entry::Vacant(view) => {
view.insert(multiplicity);
true
}
Entry::Occupied(mut view) => {
*view.get_mut() += multiplicity;
false
}
}
}
pub fn remove<Q: ?Sized>(&mut self, element: &Q) -> bool
where
T: Borrow<Q>,
Q: Hash + Eq,
{
self.remove_times(element, 1)
}
pub fn remove_times<Q: ?Sized>(&mut self, element: &Q, multiplicity: usize) -> bool
where
T: Borrow<Q>,
Q: Hash + Eq,
{
let default_value = &mut 0;
let value = self.elem_counts.get_mut(element).unwrap_or(default_value);
if *value == multiplicity {
self.elem_counts.remove(element);
return true;
}
*value = value.saturating_sub(multiplicity);
if *value == 0 {
self.elem_counts.remove(element);
return false;
}
return true;
}
pub fn take(&mut self, value: &T) -> Option<(T, usize)> {
self.elem_counts.remove_entry(value)
}
pub fn retain<F>(&mut self, mut f: F)
where
F: FnMut(&T, usize) -> bool,
{
self.elem_counts.retain(|e, m| f(e, *m));
}
pub fn drain(&mut self) -> Drain<'_, T> {
Drain {
iter: self.elem_counts.drain(),
}
}
pub fn difference<'a>(&'a self, other: &'a MultiSet<T, S>) -> Difference<'a, T, S> {
Difference {
iter: self.iter(),
other,
curr: None,
remaining: 0,
}
}
pub fn symmetric_difference<'a>(
&'a self,
other: &'a MultiSet<T, S>,
) -> SymmetricDifference<'a, T, S> {
SymmetricDifference {
iter: self.difference(other).chain(other.difference(self)),
}
}
pub fn intersection<'a>(&'a self, other: &'a MultiSet<T, S>) -> Intersection<'a, T, S> {
Intersection {
iter: self.iter(),
other: other,
curr: None,
remaining: 0,
}
}
pub fn union<'a>(&'a self, other: &'a MultiSet<T, S>) -> Union<'a, T> {
Union {
iter: self.iter().chain(other.iter()),
curr: None,
remaining: 0,
}
}
pub fn contains<Q: ?Sized>(&self, value: &Q) -> bool
where
T: Borrow<Q>,
Q: Hash + Eq,
{
self.elem_counts.contains_key(value)
}
pub fn get<Q: ?Sized>(&self, element: &Q) -> Option<usize>
where
T: Borrow<Q>,
Q: Hash + Eq,
{
self.elem_counts.get(element).map(|count| *count)
}
pub fn get_element_multiplicity<Q: ?Sized>(&self, element: &Q) -> Option<(&T, &usize)>
where
T: Borrow<Q>,
Q: Hash + Eq,
{
self.elem_counts.get_key_value(element)
}
}
impl<T: Hash + Eq> From<HashMap<T, usize>> for MultiSet<T> {
fn from(map: HashMap<T, usize>) -> Self {
Self { elem_counts: map }
}
}
impl<T: Hash + Eq, S: BuildHasher + Default> Default for MultiSet<T, S> {
fn default() -> Self {
MultiSet {
elem_counts: HashMap::default(),
}
}
}
impl<T: Eq + Hash + Clone, S: BuildHasher + Default> ops::BitOr<&MultiSet<T, S>>
for &MultiSet<T, S>
{
type Output = MultiSet<T, S>;
fn bitor(self, rhs: &MultiSet<T, S>) -> MultiSet<T, S> {
self.union(rhs).cloned().collect()
}
}
impl<T: Eq + Hash + Clone, S: BuildHasher + Default> ops::BitAnd<&MultiSet<T, S>>
for &MultiSet<T, S>
{
type Output = MultiSet<T, S>;
fn bitand(self, rhs: &MultiSet<T, S>) -> MultiSet<T, S> {
self.intersection(rhs).cloned().collect()
}
}
impl<T: Eq + Hash + Clone, S: BuildHasher + Default> ops::BitXor<&MultiSet<T, S>>
for &MultiSet<T, S>
{
type Output = MultiSet<T, S>;
fn bitxor(self, rhs: &MultiSet<T, S>) -> MultiSet<T, S> {
self.symmetric_difference(rhs).cloned().collect()
}
}
impl<T: Eq + Hash + Clone, S: BuildHasher + Default> ops::Sub<&MultiSet<T, S>> for &MultiSet<T, S> {
type Output = MultiSet<T, S>;
fn sub(self, rhs: &MultiSet<T, S>) -> MultiSet<T, S> {
self.difference(rhs).cloned().collect()
}
}
impl<T: Eq + Hash + Clone, S: BuildHasher> PartialEq for MultiSet<T, S> {
fn eq(&self, other: &MultiSet<T, S>) -> bool {
self.len() == other.len()
}
}
impl<T: Eq + Hash + Clone, S: BuildHasher> Eq for MultiSet<T, S> {}
impl<T: Eq + Hash + fmt::Debug + Clone, S: BuildHasher> fmt::Debug for MultiSet<T, S> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_set().entries(self.element_counts()).finish()
}
}
impl<T: Hash + Eq + Clone, S: BuildHasher + Default> FromIterator<T> for MultiSet<T, S> {
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> MultiSet<T, S> {
let iter = iter.into_iter();
let mut mset: MultiSet<T, S> = MultiSet::with_hasher(Default::default());
for key in iter {
mset.insert(key);
}
mset
}
}
impl<T: Hash + Eq + Clone, S: BuildHasher + Default> FromIterator<(T, usize)> for MultiSet<T, S> {
fn from_iter<I: IntoIterator<Item = (T, usize)>>(iter: I) -> MultiSet<T, S> {
let mut mset = MultiSet::with_hasher(Default::default());
mset.extend(iter);
mset
}
}
impl<T: Hash + Eq + Clone, S: BuildHasher + Default> IntoIterator for MultiSet<T, S> {
type Item = (T, usize);
type IntoIter = IntoIter<T>;
fn into_iter(self) -> IntoIter<T> {
IntoIter {
iter: self.elem_counts.into_iter(),
}
}
}
impl<'a, T: Hash + Eq + Clone, S: BuildHasher> IntoIterator for &'a MultiSet<T, S> {
type Item = (&'a T, &'a usize);
type IntoIter = Iter<'a, T>;
fn into_iter(self) -> <Self as IntoIterator>::IntoIter {
self.iter()
}
}
impl<T: Eq + Hash + Clone, S: BuildHasher> Extend<(T, usize)> for MultiSet<T, S> {
fn extend<I: IntoIterator<Item = (T, usize)>>(&mut self, iter: I) {
for (key, value) in iter.into_iter() {
self.insert_times(key, value);
}
}
}
impl<'a, T: Eq + Hash + Clone, S: BuildHasher> Extend<(&'a T, &'a usize)> for MultiSet<T, S> {
fn extend<I: IntoIterator<Item = (&'a T, &'a usize)>>(&mut self, iter: I) {
for (key, value) in iter.into_iter().map(|(k, v)| ((*k).clone(), (*v).clone())) {
self.insert_times(key, value);
}
}
}
impl<T: Eq + Hash + Clone, S: BuildHasher + Default> Extend<T> for MultiSet<T, S> {
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
for key in iter.into_iter() {
self.insert(key);
}
}
}
impl<'a, T: Eq + Hash + Clone, S: BuildHasher + Default> Extend<&'a T> for MultiSet<T, S> {
fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) {
for key in iter.into_iter().map(|k| (*k).clone()) {
self.insert(key.clone());
}
}
}
#[derive(Debug)]
pub struct ElementCounts<'a, T: 'a> {
iter: hash_map::Iter<'a, T, usize>,
}
impl<T> Clone for ElementCounts<'_, T> {
fn clone(&self) -> Self {
ElementCounts {
iter: self.iter.clone(),
}
}
}
impl<'a, T> Iterator for ElementCounts<'a, T> {
type Item = (&'a T, &'a usize);
fn next(&mut self) -> Option<(&'a T, &'a usize)> {
self.iter.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
impl<T> ExactSizeIterator for ElementCounts<'_, T> {
fn len(&self) -> usize {
self.iter.len()
}
}
impl<T> FusedIterator for ElementCounts<'_, T> {}
pub type Elements<'a, T> = std::collections::hash_map::Keys<'a, T, usize>;
#[derive(Debug)]
pub struct Iter<'a, T: 'a> {
iter: hash_map::Iter<'a, T, usize>,
}
impl<T> Clone for Iter<'_, T> {
fn clone(&self) -> Self {
Iter {
iter: self.iter.clone(),
}
}
}
impl<'a, T> Iterator for Iter<'a, T> {
type Item = (&'a T, &'a usize);
fn next(&mut self) -> Option<(&'a T, &'a usize)> {
self.iter.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
impl<T> ExactSizeIterator for Iter<'_, T> {
fn len(&self) -> usize {
self.iter.len()
}
}
impl<T> FusedIterator for Iter<'_, T> {}
#[derive(Debug)]
pub struct IntoIter<T> {
iter: hash_map::IntoIter<T, usize>,
}
impl<T> Iterator for IntoIter<T> {
type Item = (T, usize);
fn next(&mut self) -> Option<(T, usize)> {
self.iter.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
impl<T> ExactSizeIterator for IntoIter<T> {
fn len(&self) -> usize {
self.iter.len()
}
}
impl<T> FusedIterator for IntoIter<T> {}
#[derive(Debug)]
pub struct Drain<'a, T: 'a> {
iter: hash_map::Drain<'a, T, usize>,
}
impl<'a, T> Iterator for Drain<'a, T> {
type Item = (T, usize);
fn next(&mut self) -> Option<(T, usize)> {
self.iter.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
pub struct Intersection<'a, T: 'a, S: 'a> {
iter: Iter<'a, T>,
other: &'a MultiSet<T, S>,
curr: Option<&'a T>,
remaining: usize,
}
impl<T: Clone, S> Clone for Intersection<'_, T, S> {
fn clone(&self) -> Self {
Intersection {
iter: self.iter.clone(),
curr: self.curr.clone(),
..*self
}
}
}
impl<'a, T: Eq + Hash + Clone, S: BuildHasher> Iterator for Intersection<'a, T, S> {
type Item = &'a T;
fn next(&mut self) -> Option<&'a T> {
loop {
match self.remaining {
0 => {} _ => {
self.remaining = self.remaining - 1;
return Some(self.curr?);
}
}
let (elem, count) = self.iter.next()?;
let other_count = match self.other.get(elem) {
Some(c) => c,
None => 0usize,
};
self.curr = Some(elem);
self.remaining = min(*count, other_count);
}
}
}
impl<T: Eq + Hash + Clone, S: BuildHasher> FusedIterator for Intersection<'_, T, S> {}
impl<T: fmt::Debug + Eq + Hash + Clone, S: BuildHasher> fmt::Debug for Intersection<'_, T, S> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_list().entries(self.clone()).finish()
}
}
pub struct Difference<'a, T, S> {
iter: Iter<'a, T>,
other: &'a MultiSet<T, S>,
curr: Option<&'a T>,
remaining: usize,
}
impl<T: Clone, S> Clone for Difference<'_, T, S> {
fn clone(&self) -> Self {
Difference {
iter: self.iter.clone(),
..*self
}
}
}
impl<'a, T: Eq + Hash, S: BuildHasher> Iterator for Difference<'a, T, S> {
type Item = &'a T;
fn next(&mut self) -> Option<&'a T> {
loop {
match self.remaining {
0 => {} _ => {
self.remaining = self.remaining - 1;
return Some(self.curr?);
}
}
let (elem, count) = self.iter.next()?;
let other_count = match self.other.get(elem) {
Some(c) => c,
None => 0usize,
};
self.curr = Some(elem);
self.remaining = count.saturating_sub(other_count);
}
}
}
impl<T: Eq + Hash + Clone, S: BuildHasher> FusedIterator for Difference<'_, T, S> {}
impl<T: fmt::Debug + Eq + Hash + Clone, S: BuildHasher> fmt::Debug for Difference<'_, T, S> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_list().entries(self.clone()).finish()
}
}
pub struct SymmetricDifference<'a, T: 'a, S: 'a> {
iter: Chain<Difference<'a, T, S>, Difference<'a, T, S>>,
}
impl<T: Clone, S> Clone for SymmetricDifference<'_, T, S> {
fn clone(&self) -> Self {
SymmetricDifference {
iter: self.iter.clone(),
}
}
}
impl<'a, T: Eq + Hash + Clone, S: BuildHasher> Iterator for SymmetricDifference<'a, T, S> {
type Item = &'a T;
fn next(&mut self) -> Option<&'a T> {
self.iter.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
impl<T: fmt::Debug + Eq + Hash + Clone, S: BuildHasher> fmt::Debug
for SymmetricDifference<'_, T, S>
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_list().entries(self.clone()).finish()
}
}
pub struct Union<'a, T: 'a> {
iter: Chain<Iter<'a, T>, Iter<'a, T>>,
curr: Option<&'a T>,
remaining: usize,
}
impl<T: Clone> Clone for Union<'_, T> {
fn clone(&self) -> Self {
Union {
iter: self.iter.clone(),
..*self
}
}
}
impl<T: Eq + Hash + Clone> FusedIterator for Union<'_, T> {}
impl<'a, T: Eq + Hash + Clone> Iterator for Union<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<&'a T> {
loop {
match self.remaining {
0 => {} _ => {
self.remaining = self.remaining - 1;
return Some(self.curr?);
}
}
let (elem, count) = self.iter.next()?;
self.curr = Some(elem);
self.remaining = *count;
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
impl<T: fmt::Debug + Eq + Hash + Clone> fmt::Debug for Union<'_, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_list().entries(self.clone()).finish()
}
}