Bi-directional dictionary.
| 133 | |
| 134 | |
| 135 | class BiDict(UserDict[K, V]): |
| 136 | """ |
| 137 | Bi-directional dictionary. |
| 138 | """ |
| 139 | |
| 140 | _inv: dict[V, list[K]] |
| 141 | |
| 142 | def __init__(self, *args, **kwargs): |
| 143 | |
| 144 | self._inv = {} |
| 145 | |
| 146 | super().__init__(*args, **kwargs) |
| 147 | |
| 148 | def __setitem__(self, k: K, v: V): |
| 149 | |
| 150 | super().__setitem__(k, v) |
| 151 | |
| 152 | if v in self._inv: |
| 153 | self._inv[v].append(k) |
| 154 | else: |
| 155 | self._inv[v] = [k] |
| 156 | |
| 157 | @property |
| 158 | def inv(self) -> dict[V, list[K]]: |
| 159 | |
| 160 | return self._inv |
| 161 | |
| 162 | def clear(self): |
| 163 | |
| 164 | super().clear() |
| 165 | self._inv.clear() |
| 166 | |
| 167 | def __delitem__(self, k: K): |
| 168 | |
| 169 | v = self.data.pop(k) |
| 170 | |
| 171 | # if needed in one-many cases |
| 172 | if v in self._inv: |
| 173 | # remove the inverse mapping |
| 174 | inv = self._inv[v] |
| 175 | inv.remove(k) |
| 176 | |
| 177 | # if needed remove the item completely |
| 178 | if not inv: |
| 179 | del self._inv[v] |
| 180 | |
| 181 | |
| 182 | def instance_of(obj: object, *args: object) -> bool: |