Skip to content

Commit d5c14d3

Browse files
committed
Improve README
1 parent 0490426 commit d5c14d3

File tree

1 file changed

+84
-7
lines changed

1 file changed

+84
-7
lines changed

Multiset/README.markdown

Lines changed: 84 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,89 @@
1-
# An implementation of the multiset data stucture
1+
# Multiset
22

3-
## Usage
3+
A multiset (also known as a bag) is a data structure similar to a regular set, but it can store multiple instances of the same element.
4+
5+
The following all represent the same *set*, but do not represent the same *multiset*.
6+
7+
```
8+
[1, 3, 2]
9+
[1, 3, 2, 2]
10+
```
11+
12+
In this multiset implementation, ordering is unimportant. So these two multisets are identical:
13+
14+
```
15+
[1, 2, 2]
16+
[2, 1, 2]
17+
```
18+
19+
Typical operations on a multiset are:
20+
21+
- Add an element
22+
- Remove an element
23+
- Get the count for an element (the number of times it's been added)
24+
- Get the count for the whole set (the number of items that have been added)
25+
- Check whether it is a subset of another multiset
26+
27+
## Implementation
28+
29+
Under the hood, this implementation of Multiset uses a dictionary to store a mapping of elements to the number of times they've been added.
30+
31+
Here's the essence of it:
32+
33+
``` swift
34+
public struct Multiset<Element: Hashable> {
35+
fileprivate var storage: [Element: UInt]
36+
37+
public init() {
38+
storage = [:]
39+
}
40+
```
41+
42+
And here's how you'd use this class to create a multiset of strings:
43+
44+
``` swift
45+
var set = Multiset<String>()
46+
```
47+
48+
Adding an element is a case of incrementing the counter for that element, or setting it to 1 if it doesn't already exist:
49+
50+
``` swift
51+
public mutating func add (_ elem: Element) {
52+
if let currentCount = storage[elem] {
53+
storage[elem] = currentCount + 1;
54+
} else {
55+
storage[elem] = 1
56+
}
57+
}
58+
```
59+
60+
Here's how you'd use this method to add to the set we created earlier:
61+
62+
```swift
63+
set.add("foo")
64+
set.add("foo")
65+
```
66+
67+
Our set now contains two elements, both the string "foo".
68+
69+
Removing an element works much the same way as adding; decrement the counter for the element, or remove it from the underlying dictionary if its value is 1 before removal.
70+
71+
``` swift
72+
public mutating func remove (_ elem: Element) {
73+
if let currentCount = storage[elem] {
74+
if currentCount > 1 {
75+
storage[elem] = currentCount - 1
76+
} else {
77+
storage.removeValue(forKey: elem)
78+
}
79+
}
80+
}
81+
```
82+
83+
Getting the count for an item is simple: we just return the value for the given item in the internal dictionary.
484

585
``` swift
6-
var b = Multiset<Character>();
7-
for c in "hello".characters {
8-
b.add(c)
86+
public func count(for key: Element) -> UInt {
87+
return storage[key] ?? 0
988
}
10-
let count = b.count // count is 5
11-
let lcount = b.count(for: "l") // lcount is 2
1289
```

0 commit comments

Comments
 (0)