Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

libcollections: Add a Multiset data structure. #15623

Closed
wants to merge 13 commits into from
Closed
54 changes: 54 additions & 0 deletions src/libcollections/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,60 @@ pub trait MutableSet<T>: Set<T> + Mutable {
fn remove(&mut self, value: &T) -> bool;
}

/// A multiset is an unordered collection of objects in which each object can
/// appear multiple times. This trait represents actions which can be performed
/// on multisets to iterate over them.
pub trait Multiset<T>: Collection {
/// Return the number of occurrences of the value in the multiset.
fn count(&self, value: &T) -> uint;

/// Return true if the multiset has no elements in common with `other`.
fn is_disjoint(&self, other: &Self) -> bool;

/// Return true if, for any given element, the number times it occurs in the
/// multiset is not greater than the number of times it occurs in `other`.
fn is_subset(&self, other: &Self) -> bool;

/// Return true if the value occurs at least once in the multiset.
fn contains(&self, value: &T) -> bool {
self.count(value) > 0u
}

/// Return true if the multiset is a superset of another.
fn is_superset(&self, other: &Self) -> bool {
other.is_subset(self)
}

// FIXME: Ideally we would have a method to return the underlying set
// of a multiset. However, currently there's no way to have a trait method
// return a trait. We need something like associated type synonyms (see #5033)
}

/// This trait represents actions which can be performed on multisets to mutate
/// them.
pub trait MutableMultiset<T>: Multiset<T> + Mutable {
/// Add `n` occurrences of `value` to the multiset. Return true if the value
/// was not already present in the multiset.
fn insert(&mut self, value: T, n: uint) -> bool;

/// Remove `n` occurrences of `value` from the multiset. If there are less
/// than `n` occurrences, remove all occurrences. Return the number of
/// occurrences removed.
fn remove(&mut self, value: &T, n: uint) -> uint;

/// Add one occurrence of `value` to the multiset. Return true if the value
/// was not already present in the multiset.
fn insert_one(&mut self, value: T) -> bool {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not also have remove_one?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inadvertent omission. I've just added it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is definitely a minor point, but it seems like insert_one/remove_one are probably the more common methods for someone to want. Would it be better to have insert/remove be insert_one/remove_one, and then have insert_many/remove_many? At very least, this would bring the multiset interface superficially closer to the set interface.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you're right. Most of the inserts/removes will probably be one at a time. I'll change this.

self.insert(value, 1)
}

/// Remove one occurrence of `value` from the multiset. Return true if the
/// value was present in the multiset.
fn remove_one(&mut self, value: &T) -> bool {
self.remove(value, 1) > 0u
}
}

/// A double-ended sequence that allows querying, insertion and deletion at both
/// ends.
pub trait Deque<T> : Mutable {
Expand Down
Loading