multiset/
multiset.rs

1#![warn(missing_docs)]
2
3use std::borrow::{Borrow};
4use std::collections::{HashMap};
5use std::collections::hash_map;
6use std::collections::hash_map::{Entry,Keys};
7use std::hash::{Hash};
8use std::iter::{FromIterator,IntoIterator};
9use std::ops::{Add, Sub};
10use std::fmt;
11
12/// A hash-based multiset.
13#[derive(Clone)]
14pub struct HashMultiSet<K>
15{
16    elem_counts: HashMap<K, usize>,
17    size: usize,
18}
19
20/// An iterator over the items of a `HashMultiSet`.
21///
22/// This `struct` is created by the [`iter`] method on [`HashMultiSet`].
23pub struct Iter<'a, K: 'a> {
24    iter: hash_map::Iter<'a, K, usize>,
25    duplicate: Option<(&'a K, &'a usize)>,
26    duplicate_index: usize,
27}
28
29impl<'a, K> Clone for Iter<'a, K> {
30    fn clone(&self) -> Iter<'a, K> {
31        Iter {
32            iter: self.iter.clone(),
33            duplicate: self.duplicate.clone(),
34            duplicate_index: self.duplicate_index,
35        }
36    }
37}
38impl<'a, K> Iterator for Iter<'a, K> {
39    type Item = &'a K;
40
41    fn next(&mut self) -> Option<&'a K> {
42        if self.duplicate.is_none() {
43            self.duplicate = self.iter.next();
44        }
45        if self.duplicate.is_some() {
46            let (key, count) = self.duplicate.unwrap();
47            self.duplicate_index += 1;
48            if &self.duplicate_index >= count {
49                self.duplicate = None;
50                self.duplicate_index = 0;
51            }
52            Some(key)
53        } else {
54            None
55        }
56    }
57}
58
59impl<K> HashMultiSet<K> where
60    K: Eq + Hash
61{
62    /// Creates a new empty `HashMultiSet`.
63    ///
64    /// # Examples
65    ///
66    /// ```
67    /// use multiset::HashMultiSet;
68    ///
69    /// let multiset: HashMultiSet<char> = HashMultiSet::new();
70    /// ```
71    pub fn new() -> Self {
72        HashMultiSet {
73            elem_counts: HashMap::new(),
74            size: 0,
75        }
76    }
77
78    /// An iterator visiting all elements in arbitrary order, including each duplicate.
79    /// The iterator element type is `&'a K`.
80    ///
81    /// # Examples
82    ///
83    /// ```
84    /// use multiset::HashMultiSet;
85    /// let mut multiset = HashMultiSet::new();
86    /// multiset.insert(0);
87    /// multiset.insert(0);
88    /// multiset.insert(1);
89    ///
90    /// // Will print in an arbitrary order.
91    /// for x in multiset.iter() {
92    ///     println!("{}", x);
93    /// }
94    /// assert_eq!(3, multiset.iter().count());
95    /// ```
96    pub fn iter(&self) -> Iter<K> {
97        Iter {
98            iter: self.elem_counts.iter(),
99            duplicate: None,
100            duplicate_index: 0,
101        }
102    }
103
104    /// Returns true if the multiset contains no elements.
105    ///
106    /// # Examples
107    ///
108    /// ```
109    /// use multiset::HashMultiSet;
110    ///
111    /// let mut multiset = HashMultiSet::new();
112    /// assert!(multiset.is_empty());
113    /// multiset.insert(1);
114    /// assert!(!multiset.is_empty());
115    /// ```
116    pub fn is_empty(&self) -> bool {
117        self.elem_counts.is_empty()
118    }
119
120    /// Returns `true` if the multiset contains a value.
121    ///
122    /// The value may be any borrowed form of the set's value type, but
123    /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for
124    /// the value type.
125    ///
126    /// # Examples
127    ///
128    /// ```
129    /// use multiset::HashMultiSet;
130    ///
131    /// let set: HashMultiSet<_> = [1, 2, 3].iter().cloned().collect();
132    /// assert_eq!(set.contains(&1), true);
133    /// assert_eq!(set.contains(&4), false);
134    /// ```
135    pub fn contains<Q: ?Sized>(&self, value: &Q) -> bool
136        where K: Borrow<Q>,
137              Q: Hash + Eq
138    {
139        self.elem_counts.contains_key(value)
140    }
141
142    /// Counts all the elements, including each duplicate.
143    ///
144    /// # Examples
145    ///
146    /// A new empty `HashMultiSet` with 0 total elements:
147    ///
148    /// ```
149    /// use multiset::HashMultiSet;
150    ///
151    /// let multiset: HashMultiSet<char> = HashMultiSet::new();
152    /// assert_eq!(0, multiset.len());
153    /// ```
154    ///
155    /// A `HashMultiSet` from `vec![1,1,2]` has 3 total elements:
156    ///
157    /// ```
158    /// use multiset::HashMultiSet;
159    /// use std::iter::FromIterator;
160    ///
161    /// let multiset: HashMultiSet<i32> = FromIterator::from_iter(vec![1,1,2]);
162    /// assert_eq!(3, multiset.len());
163    /// ```
164    pub fn len(&self) -> usize {
165        self.size
166    }
167
168    /// Returns all the distinct elements in the `HashMultiSet`.
169    ///
170    /// # Examples
171    ///
172    /// A `HashMultiSet` from `vec![1,1,2]` has 2 distinct elements,
173    /// namely `1` and `2`, but not `3`:
174    ///
175    /// ```
176    /// use multiset::HashMultiSet;
177    /// use std::collections::HashSet;
178    /// use std::iter::FromIterator;
179    ///
180    /// let multiset: HashMultiSet<i64> = FromIterator::from_iter(vec![1,1,2]);
181    /// let distinct = multiset.distinct_elements().collect::<HashSet<_>>();
182    /// assert_eq!(2, distinct.len());
183    /// assert!(distinct.contains(&1));
184    /// assert!(distinct.contains(&2));
185    /// assert!(!distinct.contains(&3));
186    /// ```
187    pub fn distinct_elements<'a>(&'a self) -> Keys<'a, K, usize> {
188        self.elem_counts
189            .keys()
190    }
191
192    /// Inserts an element.
193    ///
194    /// # Examples
195    ///
196    /// Insert `5` into a new `HashMultiSet`:
197    ///
198    /// ```
199    /// use multiset::HashMultiSet;
200    ///
201    /// let mut multiset: HashMultiSet<i32> = HashMultiSet::new();
202    /// assert_eq!(0, multiset.count_of(&5));
203    /// multiset.insert(5);
204    /// assert_eq!(1, multiset.count_of(&5));
205    /// ```
206    pub fn insert(&mut self, val: K) {
207        self.insert_times(val, 1);
208    }
209
210    /// Inserts an element `n` times.
211    ///
212    /// # Examples
213    ///
214    /// Insert three `5`s into a new `HashMultiSet`:
215    ///
216    /// ```
217    /// use multiset::HashMultiSet;
218    ///
219    /// let mut multiset: HashMultiSet<i32> = HashMultiSet::new();
220    /// assert_eq!(0, multiset.count_of(&5));
221    /// multiset.insert_times(5,3);
222    /// assert_eq!(3, multiset.count_of(&5));
223    /// ```
224    pub fn insert_times(&mut self, val: K, n: usize) {
225        self.size += n;
226        match self.elem_counts.entry(val) {
227            Entry::Vacant(view) => {
228                view.insert(n);
229            },
230            Entry::Occupied(mut view) => {
231                let v = view.get_mut();
232                *v += n;
233            },
234        }
235    }
236
237    /// Remove an element. Removal of a nonexistent element
238    /// has no effect.
239    ///
240    /// # Examples
241    ///
242    /// Remove `5` from a new `HashMultiSet`:
243    ///
244    /// ```
245    /// use multiset::HashMultiSet;
246    ///
247    /// let mut multiset: HashMultiSet<i32> = HashMultiSet::new();
248    /// multiset.insert(5);
249    /// assert_eq!(1, multiset.count_of(&5));
250    /// assert!(multiset.remove(&5));
251    /// assert_eq!(0, multiset.count_of(&5));
252    /// assert!(!multiset.remove(&5));
253    /// ```
254    pub fn remove(&mut self, val: &K) -> bool {
255        self.remove_times(val, 1) > 0
256    }
257
258    /// Remove an element `n` times. If an element is
259    /// removed as many or more times than it appears,
260    /// it is entirely removed from the multiset.
261    ///
262    /// # Examples
263    ///
264    /// Remove `5`s from a `HashMultiSet` containing 3 of them.
265    ///
266    /// ```
267    /// use multiset::HashMultiSet;
268    ///
269    /// let mut multiset: HashMultiSet<i32> = HashMultiSet::new();
270    /// multiset.insert_times(5, 3);
271    /// assert!(multiset.count_of(&5) == 3);
272    /// assert!(multiset.remove_times(&5, 2) == 2);
273    /// assert!(multiset.len() == 1);
274    /// assert!(multiset.count_of(&5) == 1);
275    /// assert!(multiset.remove_times(&5, 1) == 1);
276    /// assert!(multiset.len() == 0);
277    /// assert!(multiset.count_of(&5) == 0);
278    /// assert!(multiset.remove_times(&5, 1) == 0);
279    /// assert!(multiset.count_of(&5) == 0);
280    /// ```
281    pub fn remove_times(&mut self, val: &K, times: usize) -> usize {
282        {
283            let entry = self.elem_counts.get_mut(val);
284            if entry.is_some() {
285                let count = entry.unwrap();
286                if *count > times {
287                    *count -= times;
288                    self.size -= times;
289                    return times
290                }
291                self.size -= *count;
292            }
293        }
294        self.elem_counts.remove(val).unwrap_or(0)
295    }
296
297    /// Remove all of an element from the multiset.
298    ///
299    /// # Examples
300    ///
301    /// Remove all `5`s from a `HashMultiSet` containing 3 of them.
302    ///
303    /// ```
304    /// use multiset::HashMultiSet;
305    ///
306    /// let mut multiset: HashMultiSet<i32> = HashMultiSet::new();
307    /// multiset.insert_times(5,3);
308    /// assert!(multiset.count_of(&5) == 3);
309    /// multiset.remove_all(&5);
310    /// assert!(multiset.count_of(&5) == 0);
311    /// ```
312    pub fn remove_all(&mut self, val: &K) {
313        self.elem_counts.remove(val);
314    }
315
316    /// Counts the occurrences of `val`.
317    ///
318    /// # Examples
319    ///
320    /// ```
321    /// use multiset::HashMultiSet;
322    ///
323    /// let mut multiset: HashMultiSet<u8> = HashMultiSet::new();
324    /// multiset.insert(0);
325    /// multiset.insert(0);
326    /// multiset.insert(1);
327    /// multiset.insert(0);
328    /// assert_eq!(3, multiset.count_of(&0));
329    /// assert_eq!(1, multiset.count_of(&1));
330    /// ```
331    pub fn count_of(&self, val: &K) -> usize {
332        self.elem_counts
333            .get(val)
334            .map_or(0, |x| *x)
335    }
336}
337
338impl<T> Add for HashMultiSet<T> where
339    T: Eq + Hash + Clone
340{
341    type Output = HashMultiSet<T>;
342
343    /// Combine two `HashMultiSet`s by adding the number of each
344    /// distinct element.
345    ///
346    /// # Examples
347    ///
348    /// ```
349    /// use multiset::HashMultiSet;
350    /// use std::iter::FromIterator;
351    ///
352    /// let lhs: HashMultiSet<isize> = FromIterator::from_iter(vec![1,2,3]);
353    /// let rhs: HashMultiSet<isize> = FromIterator::from_iter(vec![1,1,4]);
354    /// let combined = lhs + rhs;
355    /// assert_eq!(3, combined.count_of(&1));
356    /// assert_eq!(1, combined.count_of(&2));
357    /// assert_eq!(1, combined.count_of(&3));
358    /// assert_eq!(1, combined.count_of(&4));
359    /// assert_eq!(0, combined.count_of(&5));
360    /// ```
361    fn add(self, rhs: HashMultiSet<T>) ->  HashMultiSet<T> {
362        let mut ret: HashMultiSet<T> = HashMultiSet::new();
363        for val in self.distinct_elements() {
364            let count = self.count_of(val);
365            ret.insert_times((*val).clone(), count);
366        }
367        for val in rhs.distinct_elements() {
368            let count = rhs.count_of(val);
369            ret.insert_times((*val).clone(), count);
370        }
371        ret
372    }
373}
374
375impl<T> Sub for HashMultiSet<T> where
376    T: Eq + Hash + Clone
377{
378    type Output = HashMultiSet<T>;
379
380    /// Combine two `HashMultiSet`s by removing elements
381    /// in the second multiset from the first. As with `remove()`
382    /// (and set difference), excess elements in the second
383    /// multiset are ignored.
384    ///
385    /// # Examples
386    ///
387    /// ```
388    /// use multiset::HashMultiSet;
389    /// use std::iter::FromIterator;
390    ///
391    /// let lhs: HashMultiSet<isize> = FromIterator::from_iter(vec![1,2,3]);
392    /// let rhs: HashMultiSet<isize> = FromIterator::from_iter(vec![1,1,4]);
393    /// let combined = lhs - rhs;
394    /// assert_eq!(0, combined.count_of(&1));
395    /// assert_eq!(1, combined.count_of(&2));
396    /// assert_eq!(1, combined.count_of(&3));
397    /// assert_eq!(0, combined.count_of(&4));
398    /// ```
399    fn sub(self, rhs: HashMultiSet<T>) ->  HashMultiSet<T> {
400        let mut ret = self.clone();
401        for val in rhs.distinct_elements() {
402            let count = rhs.count_of(val);
403            ret.remove_times(val, count);
404        }
405        ret
406    }
407}
408
409impl<A> FromIterator<A> for HashMultiSet<A> where
410    A: Eq + Hash
411{
412    /// Creates a new `HashMultiSet` from the elements in an iterable.
413    ///
414    /// # Examples
415    ///
416    /// Count occurrences of each `char` in `"hello world"`:
417    ///
418    /// ```
419    /// use multiset::HashMultiSet;
420    /// use std::iter::FromIterator;
421    ///
422    /// let vals = vec!['h','e','l','l','o',' ','w','o','r','l','d'];
423    /// let multiset: HashMultiSet<char> = FromIterator::from_iter(vals);
424    /// assert_eq!(1, multiset.count_of(&'h'));
425    /// assert_eq!(3, multiset.count_of(&'l'));
426    /// assert_eq!(0, multiset.count_of(&'z'));
427    /// ```
428    fn from_iter<T>(iterable: T) -> HashMultiSet<A> where
429        T: IntoIterator<Item=A>
430    {
431        let mut multiset: HashMultiSet<A> = HashMultiSet::new();
432        for elem in iterable.into_iter() {
433            multiset.insert(elem);
434        }
435        multiset
436    }
437}
438
439impl<T> PartialEq for HashMultiSet<T>
440where
441    T: Eq + Hash,
442{
443    fn eq(&self, other: &HashMultiSet<T>) -> bool {
444        if self.len() != other.len() {
445            return false;
446        }
447
448        self.elem_counts.iter().all(|(key, count)| {
449            other.contains(key) && other.elem_counts.get(key).unwrap() == count
450        })
451    }
452}
453
454impl<T> Eq for HashMultiSet<T>
455where
456    T: Eq + Hash,
457{
458}
459
460impl<T> fmt::Debug for HashMultiSet<T>
461where
462    T: Eq + Hash + fmt::Debug
463{
464    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
465        f.debug_set().entries(self.iter()).finish()
466    }
467}
468
469#[cfg(test)]
470mod test_multiset {
471    use super::HashMultiSet;
472
473    #[test]
474    fn test_iterate() {
475        let mut a = HashMultiSet::new();
476        for i in 0..16 {
477            a.insert(i);
478        }
479        for i in 0..8 {
480            a.insert(i);
481        }
482        for i in 0..4 {
483            a.insert(i);
484        }
485        let mut observed: u16 = 0;
486        let mut observed_twice: u16 = 0;
487        let mut observed_thrice: u16 = 0;
488        for k in a.iter() {
489            let bit = 1 << *k;
490            if observed & bit == 0 {
491                observed |= bit;
492            } else if observed_twice & bit == 0 {
493                observed_twice |= bit;
494            } else if observed_thrice & bit == 0 {
495                observed_thrice |= bit;
496            }
497        }
498        assert_eq!(observed, 0xFFFF);
499        assert_eq!(observed_twice, 0xFF);
500        assert_eq!(observed_thrice, 0xF);
501    }
502
503    #[test]
504    fn test_eq() {
505        let mut s1 = HashMultiSet::new();
506        s1.insert(0);
507        s1.insert(1);
508        s1.insert(1);
509        let mut s2 = HashMultiSet::new();
510        s2.insert(0);
511        s2.insert(1);
512        assert!(s1 != s2);
513        s2.insert(1);
514        assert_eq!(s1, s2);
515    }
516}