Source code for titan_pylib.data_structures.set.hashed_multiset
1from typing import Iterator, Hashable
2
3
[docs]
4class HashedMultiset:
5
6 def __init__(self, a: list[Hashable] = []):
7 d = {}
8 for e in a:
9 if e in d:
10 d[e] += 1
11 else:
12 d[e] = 1
13 self._data = d
14 self._len = len(a)
15
[docs]
16 def add(self, key: Hashable, val: int = 1) -> None:
17 if key in self._data:
18 self._data[key] += val
19 else:
20 self._data[key] = val
21 self._len += val
22
[docs]
23 def discard(self, key: Hashable, val: int = 1) -> None:
24 if key not in self._data:
25 return
26 if self._data[key] > val:
27 self._len -= val
28 self._data[key] -= val
29 else:
30 self._len -= self._data[key]
31 del self._data[key]
32
[docs]
33 def discard_all(self, key: Hashable) -> None:
34 if key not in self._data:
35 return
36 self._len -= self._data[key]
37 del self._data[key]
38
[docs]
39 def count(self, key: Hashable) -> int:
40 return self._data.get(key, 0)
41
[docs]
42 def len_elm(self) -> int:
43 return len(self._data)
44
[docs]
45 def keys(self) -> Iterator[Hashable]:
46 for k in self._data.keys():
47 yield k
48
[docs]
49 def values(self) -> Iterator[int]:
50 for v in self._data.values():
51 yield v
52
[docs]
53 def items(self) -> Iterator[Hashable]:
54 for item in self._data.items():
55 yield item
56
[docs]
57 def clear(self) -> None:
58 self._data = {}
59 self._len = 0
60 self._len_elm = 0
61
62 def __eq__(self, other):
63 if isinstance(other, HashedMultiset):
64 d = other._data
65 elif hasattr(other, "items"):
66 d = other
67 else:
68 raise TypeError
69 for k, v in self._data.items():
70 if k not in d or d[k] != v:
71 return False
72 for k, v in d.items():
73 if k not in self._data or self._data[k] != v:
74 return False
75 return True
76
77 def __contains__(self, key: Hashable):
78 return key in self._data
79
80 def __len__(self):
81 return self._len