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}