stl_treemap.tree_multimap

Ordered multimap backed by a red-black tree.

  1"""Ordered multimap backed by a red-black tree."""
  2
  3from __future__ import annotations
  4
  5from collections import UserDict
  6from collections.abc import Callable, Collection, Iterable
  7from typing import Any
  8
  9from stl_treemap.insertion_result import InsertionResult
 10from stl_treemap.iterators import ReverseIterator, TreeIterator
 11from stl_treemap.policies import KeyValuePolicy
 12from stl_treemap.py_iterators import PyIterator, PyReverseIterator
 13from stl_treemap.tree import Tree
 14from stl_treemap.tree_node import TreeNode
 15
 16
 17class TreeMultiMap[K, V](Collection[K]):
 18    """
 19    Ordered map allowing multiple entries with the same key, backed by a red-black tree.
 20
 21    Unlike TreeMap, duplicate keys are permitted. Entries with equal keys appear
 22    in insertion order and are kept in their key's sorted position relative to
 23    entries with different keys. Lookup, insertion, and deletion are all O(log n).
 24
 25    Example::
 26
 27        m = TreeMultiMap()
 28        m[2] = "b1"
 29        m[2] = "b2"
 30        m[1] = "a"
 31        for key, value in m:
 32            print(f"{key}: {value}")
 33        # 1: a
 34        # 2: b1
 35        # 2: b2
 36    """
 37
 38    def __init__(self, iterable: Iterable[tuple[K, V]] | None = None, **kwargs) -> None:
 39        """
 40        Create an empty multimap, or pre-populate it from an iterable of (key, value) pairs.
 41
 42        Each pair in *iterable* is inserted independently; duplicate keys are kept.
 43
 44        Args:
 45            iterable: Optional iterable of (key, value) tuples.
 46            kwargs: Another way to provide key-value pairs.
 47
 48        Raises:
 49            TypeError: When *iterable* is not iterable.
 50
 51        Example::
 52
 53            m = TreeMultiMap()
 54            m = TreeMultiMap([[2, "B"], [1, "A"], [2, "B2"]])
 55            m = TreeMultiMap({2: "B", 1: "A", 3: "C"})
 56            m = TreeMultiMap(A=1, B=2)  # {"A": 1, "B": 2}
 57
 58        """
 59        self._t: Tree[K, V] = Tree()
 60        self._t.value_policy = KeyValuePolicy()
 61        if iterable is not None:
 62            self.update(iterable)
 63        if kwargs:
 64            self.update(kwargs.items())
 65
 66    def update(self, iterable: Iterable[tuple[K, V]]) -> None:
 67        """
 68        Add all contents from the iterable of (key, value) pairs.
 69
 70        Args:
 71            iterable: Optional iterable of (key, value) tuples.
 72
 73        Raises:
 74            TypeError: When *iterable* is not iterable.
 75
 76        Example::
 77
 78            TreeMultiMap().update(TreeMultiMap({2: "B", 1: "A", 3: "C"}))
 79            TreeMultiMap().update({2: "B", 1: "A", 3: "C"})
 80            TreeMultiMap().update({2: "B", 1: "A", 3: "C"}.items())
 81            TreeMultiMap().update([[2, "B"], [1, "A"], [3, "C"]])
 82
 83        """
 84        if isinstance(iterable, (dict, UserDict, TreeMultiMap)):
 85            for k, v in iterable.items():
 86                self.set(k, v)
 87        elif hasattr(iterable, "__iter__"):
 88            for k, v in iterable:
 89                self.set(k, v)
 90        else:
 91            raise TypeError("TreeMultiMap accepts only iterable objects")
 92
 93    # ------------------------------------------------------------------
 94    # Python dict-compatible methods
 95    # ------------------------------------------------------------------
 96
 97    def clear(self) -> None:
 98        """
 99        Remove all key-value pairs.
100
101        Example::
102
103            m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
104            m.clear()
105            len(m)  # 0
106
107        """
108        self._t.clear()
109
110    def delete(self, key: K) -> None:
111        """
112        @private Remove the first entry with *key*; does nothing if the key is absent.
113
114        When multiple entries share the same key, only the first one is removed.
115        Call repeatedly or use erase() to remove all of them.
116
117        Example::
118
119            m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
120            m.delete(2)  # removes the first entry with key 2
121            str(m)  # "{1:A,2:C}"
122            m.delete(99)  # no-op
123
124        """
125        it = self._t.find(key)
126        if not it.equals(self._t.end()):
127            self._t.erase(it.node)
128
129    def get(self, key: K, default: V | None = None) -> V | None:
130        """
131        Return the value of the first entry with *key*, or *default* if absent.
132
133        Args:
134            key: Key to look up.
135            default: Value returned when *key* is not in the map.
136
137        Example::
138
139            m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
140            m.get(2)  # "B"  — first entry with key 2
141            m.get(4)  # None
142            m.get(4, "Z")  # "Z"
143
144        """
145        it = self._t.find(key)
146        if not it.equals(self._t.end()):
147            return it.value
148        return default
149
150    def has(self, key: K) -> bool:
151        """
152        @private Return True when at least one entry with *key* exists in the map.
153
154        Example::
155
156            m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
157            m.has(2)  # True
158            m.has(4)  # False
159
160        """
161        it = self._t.find(key)
162        return not it.equals(self._t.end())
163
164    def set(self, key: K, value: V) -> None:
165        """
166        @private Add a new *(key, value)* entry, even when *key* already exists.
167
168        This is the defining behaviour of a multimap: duplicate keys are always
169        accepted, so calling ``set()`` twice with the same key creates two
170        distinct entries.
171
172        Example::
173
174            m = TreeMultiMap()
175            m.set(1, "A")
176            m.set(1, "B")  # second entry with key 1
177            list(m.values())  # ["A", "B"]
178
179        """
180        n: TreeNode[K, V] = TreeNode()
181        n.key = key
182        n.value = value
183        self._t.insert_multi(n)
184
185    def items(self) -> PyIterator[tuple[K, V]]:
186        """
187        Return a forward iterator over (key, value) pairs in ascending key order.
188
189        Example::
190
191            m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
192            for key, value in m.items():
193                print(f"key: {key}, value: {value}")
194            # key: 1, value: A
195            # key: 2, value: B
196            # key: 2, value: C
197
198        """
199        return self._t.items()
200
201    def keys(self) -> PyIterator[K]:
202        """
203        Return a forward iterator over keys in ascending order (including duplicates).
204
205        Example::
206
207            m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
208            list(m.keys())  # [1, 2, 2]
209            list(m.keys().backwards())  # [2, 2, 1]
210
211        """
212        return self._t.keys()
213
214    def values(self) -> PyIterator[V]:
215        """
216        Return a forward iterator over values in ascending key order.
217
218        Example::
219
220            m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
221            list(m.values())  # ["A", "B", "C"]
222            list(m.values().backwards())  # ["C", "B", "A"]
223
224        """
225        return self._t.values()
226
227    @property
228    def size(self) -> int:
229        """
230        @private Total number of entries in the map, counting each duplicate separately.
231
232        Example::
233
234            m = TreeMultiMap([[2, "B"], [2, "C"], [1, "A"]])
235            m.size  # 3
236
237        """
238        return self._t.size()
239
240    def __getitem__(self, key: K) -> V:
241        """
242        Return the value of the first entry with *key*.
243
244        Args:
245            key: Key to look up.
246
247        Returns:
248            Value of the first matching entry.
249
250        Raises:
251            KeyError: When *key* is not present.
252
253        Example::
254
255            m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
256            m[2]  # "B"  — first entry with key 2
257            m[4]  # raises KeyError
258
259        """
260        it = self._t.find(key)
261        if not it.equals(self._t.end()):
262            return it.value
263        raise KeyError(f"Key {key} not found")
264
265    def __setitem__(self, key: K, value: V) -> None:
266        """
267        Add a new *(key, value)* entry (same as set()).
268
269        Unlike a dict, this never replaces an existing entry; it always adds a new one.
270
271        Args:
272            key: Key for the new entry.
273            value: Value to associate with the key.
274
275        Example::
276
277            m = TreeMultiMap()
278            m[1] = "A"
279            m[1] = "B"  # adds a second entry, does NOT replace
280            list(m.values())  # ["A", "B"]
281
282        """
283        self.set(key, value)
284
285    def __contains__(self, key: K) -> bool:
286        """
287        Return True if at least one entry with *key* exists.
288
289        Args:
290            key: Key to check.
291
292        Example::
293
294            m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
295            2 in m  # True
296            4 in m  # False
297
298        """
299        return self.has(key)
300
301    def __iter__(self) -> PyIterator[K]:
302        """
303        Iterate over (key, value) pairs in ascending key order.
304
305        Example::
306
307            m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
308            for key in m:
309                print(f"{key}")
310            # 1
311            # 2
312            # 2
313
314        """
315        return self._t.keys()
316
317    def __len__(self) -> int:
318        """
319        Return the total number of entries, counting each duplicate separately.
320
321        Example::
322
323            m = TreeMultiMap([[2, "B"], [2, "C"], [1, "A"]])
324            len(m)  # 3
325
326        """
327        return self._t.size()
328
329    def __str__(self) -> str:
330        """
331        Return a string representation in the form {key1:value1,key2:value2,...}.
332
333        Duplicate keys appear multiple times in the output.
334
335        Example::
336
337            m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
338            str(m)  # "{1:A,2:B,2:C}"
339
340        """
341        return str(self._t)
342
343    def __repr__(self) -> str:
344        """
345        Return a string representation of the container's contents.
346
347        Example::
348
349            m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
350            repr(m)  # "{1:A,2:B,2:C}"
351
352        """
353        return self.__str__()
354
355    def __delitem__(self, key: K) -> None:
356        """
357        Remove **ONLY** the first entry with *key*, or raise KeyError when absent.
358
359        Args:
360            key: Key to remove.
361
362        Raises:
363            KeyError: When *key* is not present.
364
365        Example::
366
367            m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
368            del m[2]  # removes first entry with key 2; m is now {1:A,2:C}
369            del m[99]  # raises KeyError
370
371        """
372        it = self._t.find(key)
373        if not it.equals(self._t.end()):
374            self._t.erase(it.node)
375        else:
376            raise KeyError(f"Key {key} not found")
377
378    def pop(self, key: K, default: V | None = None) -> V | None:
379        """
380        Remove **ONLY** the first entry with *key* and return its value, or return *default*.
381
382        Args:
383            key: Key to remove.
384            default: Value to return when *key* is not present.
385
386        Example::
387
388            m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
389            m.pop(2)  # "B", m is now {1:A,2:C}
390            m.pop(9)  # None, m is unchanged
391            m.pop(9, "Z")  # "Z", m is unchanged
392
393        """
394        it = self._t.find(key)
395        if not it.equals(self._t.end()):
396            res = it.value
397            self._t.erase(it.node)
398            return res
399        return default
400
401    def popitem(self, key: K) -> tuple[K, V]:
402        """
403        Remove *key* and return its first key-value tuple or raise KeyError.
404
405        Args:
406            key: Key to remove.
407
408        Example::
409
410            m = TreeMap([[1, "A"], [2, "B"], [3, "C"]])
411            m.popitem(2)  # "(2,B)", m is now {1:A,3:C}
412            m.popitem(9)  # raises KeyError
413
414        """
415        iter = self.find(key)
416        if not iter.equals(self.end()):
417            k = iter.key
418            v = iter.value
419            self.erase(iter)
420            return (k, v)
421        raise KeyError(f"Key {key} not found")
422
423    # ------------------------------------------------------------------
424    # Additional iteration
425    # ------------------------------------------------------------------
426
427    def backwards(self) -> PyReverseIterator[K]:
428        """
429        Return a reverse iterator over keys in descending key order (including duplicates).
430
431        Example::
432
433            m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
434            for key in m.backwards():
435                print(key)
436            # 2
437            # 2
438            # 1
439
440        """
441        return self._t.keys().backwards()
442
443    # ------------------------------------------------------------------
444    # Custom comparator
445    # ------------------------------------------------------------------
446
447    @property
448    def compare_func(self) -> Callable[[Any, Any], int]:
449        """
450        @private The current 3-way comparison function used to order keys.
451
452        The function must accept two key arguments and return a negative
453        integer, zero, or a positive integer when the first key is less
454        than, equal to, or greater than the second key.
455
456        Setting this property clears all existing entries because the
457        current ordering is no longer valid.
458
459        Example::
460
461            m = TreeMultiMap()
462            m.compare_func = lambda a, b: -1 if a < b else (1 if a > b else 0)
463            m.set(3, "C")
464            m.set(1, "A")
465            list(m.keys())  # [1, 3]
466
467        """
468        return self._t.compare
469
470    @compare_func.setter
471    def compare_func(self, func: Callable[[Any, Any], int]) -> None:
472        """@private Replace the comparison function and clear all entries."""
473        self.clear()
474        self._t.compare = func
475
476    # ------------------------------------------------------------------
477    # STL-style iterators
478    # ------------------------------------------------------------------
479
480    def begin(self) -> TreeIterator[K, V]:
481        """
482        Return a forward STL-like iterator to the first entry.
483
484        Example::
485
486            m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
487            it = m.begin()
488            while not it.equals(m.end()):
489                print(f"key: {it.key}, value: {it.value}")
490                it.next()
491            # key: 1, value: A
492            # key: 2, value: B
493            # key: 2, value: C
494
495        """
496        return self._t.begin()
497
498    def end(self) -> TreeIterator[K, V]:
499        """
500        Return a forward STL-like iterator past the last entry.
501
502        Example::
503
504            m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
505            it = m.begin()
506            while not it.equals(m.end()):
507                print(f"key: {it.key}, value: {it.value}")
508                it.next()
509
510        """
511        return self._t.end()
512
513    def find(self, key: K) -> TreeIterator[K, V]:
514        """
515        Return a forward iterator to the first entry with *key*, or end() if absent.
516
517        When multiple entries share the same key, the iterator points to the first one.
518        Use lower_bound() / upper_bound() to iterate over all entries with that key.
519
520        Example::
521
522            m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
523            it = m.find(2)
524            if not it.equals(m.end()):
525                print(f"key: {it.key}, value: {it.value}")  # key: 2, value: B
526            m.find(99).equals(m.end())  # True
527
528        """
529        return self._t.find(key)
530
531    def insert_unique(self, key: K, value: V) -> InsertionResult[TreeIterator[K, V]]:
532        """
533        Insert *(key, value)* only when *key* is not already present.
534
535        Returns:
536            InsertionResult with was_added=True when the key was new;
537            was_added=False when any entry with that key already existed.
538
539        Example::
540
541            m = TreeMultiMap()
542            res = m.insert_unique(1, "A")
543            res.was_added  # True
544            res2 = m.insert_unique(1, "B")
545            res2.was_added  # False — key 1 already exists
546
547        """
548        n: TreeNode[K, V] = TreeNode()
549        n.key = key
550        n.value = value
551        return self._t.insert_unique(n)
552
553    def insert_or_replace(self, key: K, value: V) -> InsertionResult[TreeIterator[K, V]]:
554        """
555        Insert *(key, value)*, replacing the first existing entry when *key* already exists.
556
557        Returns:
558            InsertionResult with was_added=True on new insertion, or
559            was_replaced=True and the updated iterator on replacement.
560
561        Example::
562
563            m = TreeMultiMap()
564            res = m.insert_or_replace(1, "A")
565            res.was_added  # True
566            res2 = m.insert_or_replace(1, "B")
567            res2.was_replaced  # True
568            res2.iterator.value  # "B"
569
570        """
571        n: TreeNode[K, V] = TreeNode()
572        n.key = key
573        n.value = value
574        return self._t.insert_or_replace(n)
575
576    def insert_multi(self, key: K, value: V) -> InsertionResult[TreeIterator[K, V]]:
577        """
578        Insert *(key, value)* unconditionally, always creating a new entry.
579
580        This is the multi-key insertion that makes TreeMultiMap distinct from TreeMap.
581
582        Returns:
583            InsertionResult with was_added=True and an iterator to the new entry.
584
585        Example::
586
587            m = TreeMultiMap()
588            res = m.insert_multi(1, "A")
589            res.was_added  # True
590            res2 = m.insert_multi(1, "B")
591            res2.was_added  # True — second entry with key 1 added
592            res2.iterator.prev()
593            res2.iterator.value  # "A"
594
595        """
596        n: TreeNode[K, V] = TreeNode()
597        n.key = key
598        n.value = value
599        return self._t.insert_multi(n)
600
601    def erase(self, iterator: TreeIterator[K, V]) -> None:
602        """
603        Remove the entry pointed to by *iterator*.
604
605        Example::
606
607            m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
608            it = m.find(2)
609            m.erase(it)
610            str(m)  # "{1:A,2:C}"
611
612        """
613        self._t.erase(iterator.node)
614
615    def lower_bound(self, key: K) -> TreeIterator[K, V]:
616        """
617        Return an STL-like iterator to the first entry with key >= *key*, or end().
618
619        Combined with upper_bound(), this gives a half-open range over all
620        entries that share the same key.
621
622        Example::
623
624            m = TreeMultiMap([[2, "B1"], [2, "B2"], [4, "D"]])
625            lo = m.lower_bound(2)
626            hi = m.upper_bound(2)
627            it = lo
628            while not it.equals(hi):
629                print(it.value)  # B1, B2
630                it.next()
631
632        """
633        return self._t.lower_bound(key)
634
635    def rbegin(self) -> ReverseIterator[K, V]:
636        """
637        Return a reverse STL-like iterator to the entry with the largest key.
638
639        Example::
640
641            m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
642            it = m.rbegin()
643            while not it.equals(m.rend()):
644                print(f"key: {it.key}, value: {it.value}")
645                it.next()
646            # key: 2, value: C
647            # key: 2, value: B
648            # key: 1, value: A
649
650        """
651        return self._t.rbegin()
652
653    def rend(self) -> ReverseIterator[K, V]:
654        """
655        Return a reverse STL-like iterator before the entry with the smallest key.
656
657        Example::
658
659            m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
660            it = m.rbegin()
661            while not it.equals(m.rend()):
662                print(f"key: {it.key}, value: {it.value}")
663                it.next()
664
665        """
666        return self._t.rend()
667
668    def upper_bound(self, key: K) -> TreeIterator[K, V]:
669        """
670        Return an STL-like iterator to the first entry with key > *key*, or end().
671
672        Combined with lower_bound(), this gives a half-open range over all
673        entries that share the same key.
674
675        Example::
676
677            m = TreeMultiMap([[2, "B1"], [2, "B2"], [4, "D"]])
678            lo = m.lower_bound(2)
679            hi = m.upper_bound(2)
680            it = lo
681            while not it.equals(hi):
682                print(it.value)  # B1, B2
683                it.next()
684
685        """
686        return self._t.upper_bound(key)
687
688    def first(self) -> tuple[K, V] | None:
689        """
690        Return the first (key, value) pair, or None when the map is empty.
691
692        Example::
693
694            m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
695            key, value = m.first()  # (1, "A")
696            TreeMultiMap().first()  # None
697
698        """
699        return self._t.first()
700
701    def last(self) -> tuple[K, V] | None:
702        """
703        Return the last (key, value) pair, or None when the map is empty.
704
705        Example::
706
707            m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
708            key, value = m.last()  # (2, "C")
709            TreeMultiMap().last()  # None
710
711        """
712        return self._t.last()
713
714    def __or__(self, other: Any) -> TreeMultiMap[K, V]:
715        """
716        Return a new multimap containing all entries from this map followed by all from *other*.
717
718        All entries are added via insert_multi, so duplicates are preserved.
719
720        Example::
721
722            m1 = TreeMultiMap([[1, "A"], [2, "B"]])
723            m2 = TreeMultiMap([[2, "X"], [3, "C"]])
724            m3 = m1 | m2
725            str(m3)  # "{1:A,2:B,2:X,3:C}"
726
727        """
728        res = TreeMultiMap[K, V](self)
729        if isinstance(other, (dict, UserDict, TreeMultiMap)) or hasattr(other, "__iter__"):
730            res.update(other)
731        else:
732            return NotImplemented
733        return res
734
735    def __ror__(self, other: Any) -> TreeMultiMap[K, V]:
736        """
737        Return a union multimap when this TreeMultiMap is on the right-hand side of ``|``.
738
739        *other*'s entries are inserted first, then this map's entries are appended.
740
741        Example::
742
743            m = TreeMultiMap([[2, "X"], [3, "C"]])
744            result = {1: "A", 2: "B"} | m
745            str(result)  # "{1:A,2:B,2:X,3:C}"
746
747        """
748        res = TreeMultiMap[K, V]()
749        if isinstance(other, (dict, UserDict, TreeMultiMap)) or hasattr(other, "__iter__"):
750            res.update(other)
751        else:
752            return NotImplemented
753        res.update(self)
754        return res
755
756    def __ior__(self, other: Any) -> TreeMultiMap[K, V]:
757        """
758        Add all entries from *other* to this multimap in-place.
759
760        Example::
761
762            m = TreeMultiMap([[1, "A"], [2, "B"]])
763            m |= {2: "X", 3: "C"}
764            str(m)  # "{1:A,2:B,2:X,3:C}"
765
766        """
767        if isinstance(other, (dict, UserDict, TreeMultiMap)) or hasattr(other, "__iter__"):
768            self.update(other)
769        else:
770            return NotImplemented
771        return self
772
773    def __copy__(self) -> TreeMultiMap[K, V]:
774        """
775        Create a shallow copy, preserving all entries including duplicates.
776
777        Example::
778
779            import copy
780
781            m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
782            m2 = copy.copy(m)
783            m2.set(3, "D")
784            str(m)  # "{1:A,2:B,2:C}"      — original unchanged
785            str(m2)  # "{1:A,2:B,2:C,3:D}"
786
787        """
788        return TreeMultiMap[K, V](self.items())
class TreeMultiMap(collections.abc.Collection[K], typing.Generic[K, V]):
 18class TreeMultiMap[K, V](Collection[K]):
 19    """
 20    Ordered map allowing multiple entries with the same key, backed by a red-black tree.
 21
 22    Unlike TreeMap, duplicate keys are permitted. Entries with equal keys appear
 23    in insertion order and are kept in their key's sorted position relative to
 24    entries with different keys. Lookup, insertion, and deletion are all O(log n).
 25
 26    Example::
 27
 28        m = TreeMultiMap()
 29        m[2] = "b1"
 30        m[2] = "b2"
 31        m[1] = "a"
 32        for key, value in m:
 33            print(f"{key}: {value}")
 34        # 1: a
 35        # 2: b1
 36        # 2: b2
 37    """
 38
 39    def __init__(self, iterable: Iterable[tuple[K, V]] | None = None, **kwargs) -> None:
 40        """
 41        Create an empty multimap, or pre-populate it from an iterable of (key, value) pairs.
 42
 43        Each pair in *iterable* is inserted independently; duplicate keys are kept.
 44
 45        Args:
 46            iterable: Optional iterable of (key, value) tuples.
 47            kwargs: Another way to provide key-value pairs.
 48
 49        Raises:
 50            TypeError: When *iterable* is not iterable.
 51
 52        Example::
 53
 54            m = TreeMultiMap()
 55            m = TreeMultiMap([[2, "B"], [1, "A"], [2, "B2"]])
 56            m = TreeMultiMap({2: "B", 1: "A", 3: "C"})
 57            m = TreeMultiMap(A=1, B=2)  # {"A": 1, "B": 2}
 58
 59        """
 60        self._t: Tree[K, V] = Tree()
 61        self._t.value_policy = KeyValuePolicy()
 62        if iterable is not None:
 63            self.update(iterable)
 64        if kwargs:
 65            self.update(kwargs.items())
 66
 67    def update(self, iterable: Iterable[tuple[K, V]]) -> None:
 68        """
 69        Add all contents from the iterable of (key, value) pairs.
 70
 71        Args:
 72            iterable: Optional iterable of (key, value) tuples.
 73
 74        Raises:
 75            TypeError: When *iterable* is not iterable.
 76
 77        Example::
 78
 79            TreeMultiMap().update(TreeMultiMap({2: "B", 1: "A", 3: "C"}))
 80            TreeMultiMap().update({2: "B", 1: "A", 3: "C"})
 81            TreeMultiMap().update({2: "B", 1: "A", 3: "C"}.items())
 82            TreeMultiMap().update([[2, "B"], [1, "A"], [3, "C"]])
 83
 84        """
 85        if isinstance(iterable, (dict, UserDict, TreeMultiMap)):
 86            for k, v in iterable.items():
 87                self.set(k, v)
 88        elif hasattr(iterable, "__iter__"):
 89            for k, v in iterable:
 90                self.set(k, v)
 91        else:
 92            raise TypeError("TreeMultiMap accepts only iterable objects")
 93
 94    # ------------------------------------------------------------------
 95    # Python dict-compatible methods
 96    # ------------------------------------------------------------------
 97
 98    def clear(self) -> None:
 99        """
100        Remove all key-value pairs.
101
102        Example::
103
104            m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
105            m.clear()
106            len(m)  # 0
107
108        """
109        self._t.clear()
110
111    def delete(self, key: K) -> None:
112        """
113        @private Remove the first entry with *key*; does nothing if the key is absent.
114
115        When multiple entries share the same key, only the first one is removed.
116        Call repeatedly or use erase() to remove all of them.
117
118        Example::
119
120            m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
121            m.delete(2)  # removes the first entry with key 2
122            str(m)  # "{1:A,2:C}"
123            m.delete(99)  # no-op
124
125        """
126        it = self._t.find(key)
127        if not it.equals(self._t.end()):
128            self._t.erase(it.node)
129
130    def get(self, key: K, default: V | None = None) -> V | None:
131        """
132        Return the value of the first entry with *key*, or *default* if absent.
133
134        Args:
135            key: Key to look up.
136            default: Value returned when *key* is not in the map.
137
138        Example::
139
140            m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
141            m.get(2)  # "B"  — first entry with key 2
142            m.get(4)  # None
143            m.get(4, "Z")  # "Z"
144
145        """
146        it = self._t.find(key)
147        if not it.equals(self._t.end()):
148            return it.value
149        return default
150
151    def has(self, key: K) -> bool:
152        """
153        @private Return True when at least one entry with *key* exists in the map.
154
155        Example::
156
157            m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
158            m.has(2)  # True
159            m.has(4)  # False
160
161        """
162        it = self._t.find(key)
163        return not it.equals(self._t.end())
164
165    def set(self, key: K, value: V) -> None:
166        """
167        @private Add a new *(key, value)* entry, even when *key* already exists.
168
169        This is the defining behaviour of a multimap: duplicate keys are always
170        accepted, so calling ``set()`` twice with the same key creates two
171        distinct entries.
172
173        Example::
174
175            m = TreeMultiMap()
176            m.set(1, "A")
177            m.set(1, "B")  # second entry with key 1
178            list(m.values())  # ["A", "B"]
179
180        """
181        n: TreeNode[K, V] = TreeNode()
182        n.key = key
183        n.value = value
184        self._t.insert_multi(n)
185
186    def items(self) -> PyIterator[tuple[K, V]]:
187        """
188        Return a forward iterator over (key, value) pairs in ascending key order.
189
190        Example::
191
192            m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
193            for key, value in m.items():
194                print(f"key: {key}, value: {value}")
195            # key: 1, value: A
196            # key: 2, value: B
197            # key: 2, value: C
198
199        """
200        return self._t.items()
201
202    def keys(self) -> PyIterator[K]:
203        """
204        Return a forward iterator over keys in ascending order (including duplicates).
205
206        Example::
207
208            m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
209            list(m.keys())  # [1, 2, 2]
210            list(m.keys().backwards())  # [2, 2, 1]
211
212        """
213        return self._t.keys()
214
215    def values(self) -> PyIterator[V]:
216        """
217        Return a forward iterator over values in ascending key order.
218
219        Example::
220
221            m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
222            list(m.values())  # ["A", "B", "C"]
223            list(m.values().backwards())  # ["C", "B", "A"]
224
225        """
226        return self._t.values()
227
228    @property
229    def size(self) -> int:
230        """
231        @private Total number of entries in the map, counting each duplicate separately.
232
233        Example::
234
235            m = TreeMultiMap([[2, "B"], [2, "C"], [1, "A"]])
236            m.size  # 3
237
238        """
239        return self._t.size()
240
241    def __getitem__(self, key: K) -> V:
242        """
243        Return the value of the first entry with *key*.
244
245        Args:
246            key: Key to look up.
247
248        Returns:
249            Value of the first matching entry.
250
251        Raises:
252            KeyError: When *key* is not present.
253
254        Example::
255
256            m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
257            m[2]  # "B"  — first entry with key 2
258            m[4]  # raises KeyError
259
260        """
261        it = self._t.find(key)
262        if not it.equals(self._t.end()):
263            return it.value
264        raise KeyError(f"Key {key} not found")
265
266    def __setitem__(self, key: K, value: V) -> None:
267        """
268        Add a new *(key, value)* entry (same as set()).
269
270        Unlike a dict, this never replaces an existing entry; it always adds a new one.
271
272        Args:
273            key: Key for the new entry.
274            value: Value to associate with the key.
275
276        Example::
277
278            m = TreeMultiMap()
279            m[1] = "A"
280            m[1] = "B"  # adds a second entry, does NOT replace
281            list(m.values())  # ["A", "B"]
282
283        """
284        self.set(key, value)
285
286    def __contains__(self, key: K) -> bool:
287        """
288        Return True if at least one entry with *key* exists.
289
290        Args:
291            key: Key to check.
292
293        Example::
294
295            m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
296            2 in m  # True
297            4 in m  # False
298
299        """
300        return self.has(key)
301
302    def __iter__(self) -> PyIterator[K]:
303        """
304        Iterate over (key, value) pairs in ascending key order.
305
306        Example::
307
308            m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
309            for key in m:
310                print(f"{key}")
311            # 1
312            # 2
313            # 2
314
315        """
316        return self._t.keys()
317
318    def __len__(self) -> int:
319        """
320        Return the total number of entries, counting each duplicate separately.
321
322        Example::
323
324            m = TreeMultiMap([[2, "B"], [2, "C"], [1, "A"]])
325            len(m)  # 3
326
327        """
328        return self._t.size()
329
330    def __str__(self) -> str:
331        """
332        Return a string representation in the form {key1:value1,key2:value2,...}.
333
334        Duplicate keys appear multiple times in the output.
335
336        Example::
337
338            m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
339            str(m)  # "{1:A,2:B,2:C}"
340
341        """
342        return str(self._t)
343
344    def __repr__(self) -> str:
345        """
346        Return a string representation of the container's contents.
347
348        Example::
349
350            m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
351            repr(m)  # "{1:A,2:B,2:C}"
352
353        """
354        return self.__str__()
355
356    def __delitem__(self, key: K) -> None:
357        """
358        Remove **ONLY** the first entry with *key*, or raise KeyError when absent.
359
360        Args:
361            key: Key to remove.
362
363        Raises:
364            KeyError: When *key* is not present.
365
366        Example::
367
368            m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
369            del m[2]  # removes first entry with key 2; m is now {1:A,2:C}
370            del m[99]  # raises KeyError
371
372        """
373        it = self._t.find(key)
374        if not it.equals(self._t.end()):
375            self._t.erase(it.node)
376        else:
377            raise KeyError(f"Key {key} not found")
378
379    def pop(self, key: K, default: V | None = None) -> V | None:
380        """
381        Remove **ONLY** the first entry with *key* and return its value, or return *default*.
382
383        Args:
384            key: Key to remove.
385            default: Value to return when *key* is not present.
386
387        Example::
388
389            m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
390            m.pop(2)  # "B", m is now {1:A,2:C}
391            m.pop(9)  # None, m is unchanged
392            m.pop(9, "Z")  # "Z", m is unchanged
393
394        """
395        it = self._t.find(key)
396        if not it.equals(self._t.end()):
397            res = it.value
398            self._t.erase(it.node)
399            return res
400        return default
401
402    def popitem(self, key: K) -> tuple[K, V]:
403        """
404        Remove *key* and return its first key-value tuple or raise KeyError.
405
406        Args:
407            key: Key to remove.
408
409        Example::
410
411            m = TreeMap([[1, "A"], [2, "B"], [3, "C"]])
412            m.popitem(2)  # "(2,B)", m is now {1:A,3:C}
413            m.popitem(9)  # raises KeyError
414
415        """
416        iter = self.find(key)
417        if not iter.equals(self.end()):
418            k = iter.key
419            v = iter.value
420            self.erase(iter)
421            return (k, v)
422        raise KeyError(f"Key {key} not found")
423
424    # ------------------------------------------------------------------
425    # Additional iteration
426    # ------------------------------------------------------------------
427
428    def backwards(self) -> PyReverseIterator[K]:
429        """
430        Return a reverse iterator over keys in descending key order (including duplicates).
431
432        Example::
433
434            m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
435            for key in m.backwards():
436                print(key)
437            # 2
438            # 2
439            # 1
440
441        """
442        return self._t.keys().backwards()
443
444    # ------------------------------------------------------------------
445    # Custom comparator
446    # ------------------------------------------------------------------
447
448    @property
449    def compare_func(self) -> Callable[[Any, Any], int]:
450        """
451        @private The current 3-way comparison function used to order keys.
452
453        The function must accept two key arguments and return a negative
454        integer, zero, or a positive integer when the first key is less
455        than, equal to, or greater than the second key.
456
457        Setting this property clears all existing entries because the
458        current ordering is no longer valid.
459
460        Example::
461
462            m = TreeMultiMap()
463            m.compare_func = lambda a, b: -1 if a < b else (1 if a > b else 0)
464            m.set(3, "C")
465            m.set(1, "A")
466            list(m.keys())  # [1, 3]
467
468        """
469        return self._t.compare
470
471    @compare_func.setter
472    def compare_func(self, func: Callable[[Any, Any], int]) -> None:
473        """@private Replace the comparison function and clear all entries."""
474        self.clear()
475        self._t.compare = func
476
477    # ------------------------------------------------------------------
478    # STL-style iterators
479    # ------------------------------------------------------------------
480
481    def begin(self) -> TreeIterator[K, V]:
482        """
483        Return a forward STL-like iterator to the first entry.
484
485        Example::
486
487            m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
488            it = m.begin()
489            while not it.equals(m.end()):
490                print(f"key: {it.key}, value: {it.value}")
491                it.next()
492            # key: 1, value: A
493            # key: 2, value: B
494            # key: 2, value: C
495
496        """
497        return self._t.begin()
498
499    def end(self) -> TreeIterator[K, V]:
500        """
501        Return a forward STL-like iterator past the last entry.
502
503        Example::
504
505            m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
506            it = m.begin()
507            while not it.equals(m.end()):
508                print(f"key: {it.key}, value: {it.value}")
509                it.next()
510
511        """
512        return self._t.end()
513
514    def find(self, key: K) -> TreeIterator[K, V]:
515        """
516        Return a forward iterator to the first entry with *key*, or end() if absent.
517
518        When multiple entries share the same key, the iterator points to the first one.
519        Use lower_bound() / upper_bound() to iterate over all entries with that key.
520
521        Example::
522
523            m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
524            it = m.find(2)
525            if not it.equals(m.end()):
526                print(f"key: {it.key}, value: {it.value}")  # key: 2, value: B
527            m.find(99).equals(m.end())  # True
528
529        """
530        return self._t.find(key)
531
532    def insert_unique(self, key: K, value: V) -> InsertionResult[TreeIterator[K, V]]:
533        """
534        Insert *(key, value)* only when *key* is not already present.
535
536        Returns:
537            InsertionResult with was_added=True when the key was new;
538            was_added=False when any entry with that key already existed.
539
540        Example::
541
542            m = TreeMultiMap()
543            res = m.insert_unique(1, "A")
544            res.was_added  # True
545            res2 = m.insert_unique(1, "B")
546            res2.was_added  # False — key 1 already exists
547
548        """
549        n: TreeNode[K, V] = TreeNode()
550        n.key = key
551        n.value = value
552        return self._t.insert_unique(n)
553
554    def insert_or_replace(self, key: K, value: V) -> InsertionResult[TreeIterator[K, V]]:
555        """
556        Insert *(key, value)*, replacing the first existing entry when *key* already exists.
557
558        Returns:
559            InsertionResult with was_added=True on new insertion, or
560            was_replaced=True and the updated iterator on replacement.
561
562        Example::
563
564            m = TreeMultiMap()
565            res = m.insert_or_replace(1, "A")
566            res.was_added  # True
567            res2 = m.insert_or_replace(1, "B")
568            res2.was_replaced  # True
569            res2.iterator.value  # "B"
570
571        """
572        n: TreeNode[K, V] = TreeNode()
573        n.key = key
574        n.value = value
575        return self._t.insert_or_replace(n)
576
577    def insert_multi(self, key: K, value: V) -> InsertionResult[TreeIterator[K, V]]:
578        """
579        Insert *(key, value)* unconditionally, always creating a new entry.
580
581        This is the multi-key insertion that makes TreeMultiMap distinct from TreeMap.
582
583        Returns:
584            InsertionResult with was_added=True and an iterator to the new entry.
585
586        Example::
587
588            m = TreeMultiMap()
589            res = m.insert_multi(1, "A")
590            res.was_added  # True
591            res2 = m.insert_multi(1, "B")
592            res2.was_added  # True — second entry with key 1 added
593            res2.iterator.prev()
594            res2.iterator.value  # "A"
595
596        """
597        n: TreeNode[K, V] = TreeNode()
598        n.key = key
599        n.value = value
600        return self._t.insert_multi(n)
601
602    def erase(self, iterator: TreeIterator[K, V]) -> None:
603        """
604        Remove the entry pointed to by *iterator*.
605
606        Example::
607
608            m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
609            it = m.find(2)
610            m.erase(it)
611            str(m)  # "{1:A,2:C}"
612
613        """
614        self._t.erase(iterator.node)
615
616    def lower_bound(self, key: K) -> TreeIterator[K, V]:
617        """
618        Return an STL-like iterator to the first entry with key >= *key*, or end().
619
620        Combined with upper_bound(), this gives a half-open range over all
621        entries that share the same key.
622
623        Example::
624
625            m = TreeMultiMap([[2, "B1"], [2, "B2"], [4, "D"]])
626            lo = m.lower_bound(2)
627            hi = m.upper_bound(2)
628            it = lo
629            while not it.equals(hi):
630                print(it.value)  # B1, B2
631                it.next()
632
633        """
634        return self._t.lower_bound(key)
635
636    def rbegin(self) -> ReverseIterator[K, V]:
637        """
638        Return a reverse STL-like iterator to the entry with the largest key.
639
640        Example::
641
642            m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
643            it = m.rbegin()
644            while not it.equals(m.rend()):
645                print(f"key: {it.key}, value: {it.value}")
646                it.next()
647            # key: 2, value: C
648            # key: 2, value: B
649            # key: 1, value: A
650
651        """
652        return self._t.rbegin()
653
654    def rend(self) -> ReverseIterator[K, V]:
655        """
656        Return a reverse STL-like iterator before the entry with the smallest key.
657
658        Example::
659
660            m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
661            it = m.rbegin()
662            while not it.equals(m.rend()):
663                print(f"key: {it.key}, value: {it.value}")
664                it.next()
665
666        """
667        return self._t.rend()
668
669    def upper_bound(self, key: K) -> TreeIterator[K, V]:
670        """
671        Return an STL-like iterator to the first entry with key > *key*, or end().
672
673        Combined with lower_bound(), this gives a half-open range over all
674        entries that share the same key.
675
676        Example::
677
678            m = TreeMultiMap([[2, "B1"], [2, "B2"], [4, "D"]])
679            lo = m.lower_bound(2)
680            hi = m.upper_bound(2)
681            it = lo
682            while not it.equals(hi):
683                print(it.value)  # B1, B2
684                it.next()
685
686        """
687        return self._t.upper_bound(key)
688
689    def first(self) -> tuple[K, V] | None:
690        """
691        Return the first (key, value) pair, or None when the map is empty.
692
693        Example::
694
695            m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
696            key, value = m.first()  # (1, "A")
697            TreeMultiMap().first()  # None
698
699        """
700        return self._t.first()
701
702    def last(self) -> tuple[K, V] | None:
703        """
704        Return the last (key, value) pair, or None when the map is empty.
705
706        Example::
707
708            m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
709            key, value = m.last()  # (2, "C")
710            TreeMultiMap().last()  # None
711
712        """
713        return self._t.last()
714
715    def __or__(self, other: Any) -> TreeMultiMap[K, V]:
716        """
717        Return a new multimap containing all entries from this map followed by all from *other*.
718
719        All entries are added via insert_multi, so duplicates are preserved.
720
721        Example::
722
723            m1 = TreeMultiMap([[1, "A"], [2, "B"]])
724            m2 = TreeMultiMap([[2, "X"], [3, "C"]])
725            m3 = m1 | m2
726            str(m3)  # "{1:A,2:B,2:X,3:C}"
727
728        """
729        res = TreeMultiMap[K, V](self)
730        if isinstance(other, (dict, UserDict, TreeMultiMap)) or hasattr(other, "__iter__"):
731            res.update(other)
732        else:
733            return NotImplemented
734        return res
735
736    def __ror__(self, other: Any) -> TreeMultiMap[K, V]:
737        """
738        Return a union multimap when this TreeMultiMap is on the right-hand side of ``|``.
739
740        *other*'s entries are inserted first, then this map's entries are appended.
741
742        Example::
743
744            m = TreeMultiMap([[2, "X"], [3, "C"]])
745            result = {1: "A", 2: "B"} | m
746            str(result)  # "{1:A,2:B,2:X,3:C}"
747
748        """
749        res = TreeMultiMap[K, V]()
750        if isinstance(other, (dict, UserDict, TreeMultiMap)) or hasattr(other, "__iter__"):
751            res.update(other)
752        else:
753            return NotImplemented
754        res.update(self)
755        return res
756
757    def __ior__(self, other: Any) -> TreeMultiMap[K, V]:
758        """
759        Add all entries from *other* to this multimap in-place.
760
761        Example::
762
763            m = TreeMultiMap([[1, "A"], [2, "B"]])
764            m |= {2: "X", 3: "C"}
765            str(m)  # "{1:A,2:B,2:X,3:C}"
766
767        """
768        if isinstance(other, (dict, UserDict, TreeMultiMap)) or hasattr(other, "__iter__"):
769            self.update(other)
770        else:
771            return NotImplemented
772        return self
773
774    def __copy__(self) -> TreeMultiMap[K, V]:
775        """
776        Create a shallow copy, preserving all entries including duplicates.
777
778        Example::
779
780            import copy
781
782            m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
783            m2 = copy.copy(m)
784            m2.set(3, "D")
785            str(m)  # "{1:A,2:B,2:C}"      — original unchanged
786            str(m2)  # "{1:A,2:B,2:C,3:D}"
787
788        """
789        return TreeMultiMap[K, V](self.items())

Ordered map allowing multiple entries with the same key, backed by a red-black tree.

Unlike TreeMap, duplicate keys are permitted. Entries with equal keys appear in insertion order and are kept in their key's sorted position relative to entries with different keys. Lookup, insertion, and deletion are all O(log n).

Example::

m = TreeMultiMap()
m[2] = "b1"
m[2] = "b2"
m[1] = "a"
for key, value in m:
    print(f"{key}: {value}")
# 1: a
# 2: b1
# 2: b2
TreeMultiMap(iterable: 'Iterable[tuple[K, V]] | None' = None, **kwargs)
39    def __init__(self, iterable: Iterable[tuple[K, V]] | None = None, **kwargs) -> None:
40        """
41        Create an empty multimap, or pre-populate it from an iterable of (key, value) pairs.
42
43        Each pair in *iterable* is inserted independently; duplicate keys are kept.
44
45        Args:
46            iterable: Optional iterable of (key, value) tuples.
47            kwargs: Another way to provide key-value pairs.
48
49        Raises:
50            TypeError: When *iterable* is not iterable.
51
52        Example::
53
54            m = TreeMultiMap()
55            m = TreeMultiMap([[2, "B"], [1, "A"], [2, "B2"]])
56            m = TreeMultiMap({2: "B", 1: "A", 3: "C"})
57            m = TreeMultiMap(A=1, B=2)  # {"A": 1, "B": 2}
58
59        """
60        self._t: Tree[K, V] = Tree()
61        self._t.value_policy = KeyValuePolicy()
62        if iterable is not None:
63            self.update(iterable)
64        if kwargs:
65            self.update(kwargs.items())

Create an empty multimap, or pre-populate it from an iterable of (key, value) pairs.

Each pair in iterable is inserted independently; duplicate keys are kept.

Args: iterable: Optional iterable of (key, value) tuples. kwargs: Another way to provide key-value pairs.

Raises: TypeError: When iterable is not iterable.

Example::

m = TreeMultiMap()
m = TreeMultiMap([[2, "B"], [1, "A"], [2, "B2"]])
m = TreeMultiMap({2: "B", 1: "A", 3: "C"})
m = TreeMultiMap(A=1, B=2)  # {"A": 1, "B": 2}
def update(self, iterable: 'Iterable[tuple[K, V]]') -> None:
67    def update(self, iterable: Iterable[tuple[K, V]]) -> None:
68        """
69        Add all contents from the iterable of (key, value) pairs.
70
71        Args:
72            iterable: Optional iterable of (key, value) tuples.
73
74        Raises:
75            TypeError: When *iterable* is not iterable.
76
77        Example::
78
79            TreeMultiMap().update(TreeMultiMap({2: "B", 1: "A", 3: "C"}))
80            TreeMultiMap().update({2: "B", 1: "A", 3: "C"})
81            TreeMultiMap().update({2: "B", 1: "A", 3: "C"}.items())
82            TreeMultiMap().update([[2, "B"], [1, "A"], [3, "C"]])
83
84        """
85        if isinstance(iterable, (dict, UserDict, TreeMultiMap)):
86            for k, v in iterable.items():
87                self.set(k, v)
88        elif hasattr(iterable, "__iter__"):
89            for k, v in iterable:
90                self.set(k, v)
91        else:
92            raise TypeError("TreeMultiMap accepts only iterable objects")

Add all contents from the iterable of (key, value) pairs.

Args: iterable: Optional iterable of (key, value) tuples.

Raises: TypeError: When iterable is not iterable.

Example::

TreeMultiMap().update(TreeMultiMap({2: "B", 1: "A", 3: "C"}))
TreeMultiMap().update({2: "B", 1: "A", 3: "C"})
TreeMultiMap().update({2: "B", 1: "A", 3: "C"}.items())
TreeMultiMap().update([[2, "B"], [1, "A"], [3, "C"]])
def clear(self) -> None:
 98    def clear(self) -> None:
 99        """
100        Remove all key-value pairs.
101
102        Example::
103
104            m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
105            m.clear()
106            len(m)  # 0
107
108        """
109        self._t.clear()

Remove all key-value pairs.

Example::

m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
m.clear()
len(m)  # 0
def get(self, key: 'K', default: 'V | None' = None) -> 'V | None':
130    def get(self, key: K, default: V | None = None) -> V | None:
131        """
132        Return the value of the first entry with *key*, or *default* if absent.
133
134        Args:
135            key: Key to look up.
136            default: Value returned when *key* is not in the map.
137
138        Example::
139
140            m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
141            m.get(2)  # "B"  — first entry with key 2
142            m.get(4)  # None
143            m.get(4, "Z")  # "Z"
144
145        """
146        it = self._t.find(key)
147        if not it.equals(self._t.end()):
148            return it.value
149        return default

Return the value of the first entry with key, or default if absent.

Args: key: Key to look up. default: Value returned when key is not in the map.

Example::

m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
m.get(2)  # "B"  — first entry with key 2
m.get(4)  # None
m.get(4, "Z")  # "Z"
def items(self) -> 'PyIterator[tuple[K, V]]':
186    def items(self) -> PyIterator[tuple[K, V]]:
187        """
188        Return a forward iterator over (key, value) pairs in ascending key order.
189
190        Example::
191
192            m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
193            for key, value in m.items():
194                print(f"key: {key}, value: {value}")
195            # key: 1, value: A
196            # key: 2, value: B
197            # key: 2, value: C
198
199        """
200        return self._t.items()

Return a forward iterator over (key, value) pairs in ascending key order.

Example::

m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
for key, value in m.items():
    print(f"key: {key}, value: {value}")
# key: 1, value: A
# key: 2, value: B
# key: 2, value: C
def keys(self) -> 'PyIterator[K]':
202    def keys(self) -> PyIterator[K]:
203        """
204        Return a forward iterator over keys in ascending order (including duplicates).
205
206        Example::
207
208            m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
209            list(m.keys())  # [1, 2, 2]
210            list(m.keys().backwards())  # [2, 2, 1]
211
212        """
213        return self._t.keys()

Return a forward iterator over keys in ascending order (including duplicates).

Example::

m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
list(m.keys())  # [1, 2, 2]
list(m.keys().backwards())  # [2, 2, 1]
def values(self) -> 'PyIterator[V]':
215    def values(self) -> PyIterator[V]:
216        """
217        Return a forward iterator over values in ascending key order.
218
219        Example::
220
221            m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
222            list(m.values())  # ["A", "B", "C"]
223            list(m.values().backwards())  # ["C", "B", "A"]
224
225        """
226        return self._t.values()

Return a forward iterator over values in ascending key order.

Example::

m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
list(m.values())  # ["A", "B", "C"]
list(m.values().backwards())  # ["C", "B", "A"]
def pop(self, key: 'K', default: 'V | None' = None) -> 'V | None':
379    def pop(self, key: K, default: V | None = None) -> V | None:
380        """
381        Remove **ONLY** the first entry with *key* and return its value, or return *default*.
382
383        Args:
384            key: Key to remove.
385            default: Value to return when *key* is not present.
386
387        Example::
388
389            m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
390            m.pop(2)  # "B", m is now {1:A,2:C}
391            m.pop(9)  # None, m is unchanged
392            m.pop(9, "Z")  # "Z", m is unchanged
393
394        """
395        it = self._t.find(key)
396        if not it.equals(self._t.end()):
397            res = it.value
398            self._t.erase(it.node)
399            return res
400        return default

Remove ONLY the first entry with key and return its value, or return default.

Args: key: Key to remove. default: Value to return when key is not present.

Example::

m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
m.pop(2)  # "B", m is now {1:A,2:C}
m.pop(9)  # None, m is unchanged
m.pop(9, "Z")  # "Z", m is unchanged
def popitem(self, key: 'K') -> 'tuple[K, V]':
402    def popitem(self, key: K) -> tuple[K, V]:
403        """
404        Remove *key* and return its first key-value tuple or raise KeyError.
405
406        Args:
407            key: Key to remove.
408
409        Example::
410
411            m = TreeMap([[1, "A"], [2, "B"], [3, "C"]])
412            m.popitem(2)  # "(2,B)", m is now {1:A,3:C}
413            m.popitem(9)  # raises KeyError
414
415        """
416        iter = self.find(key)
417        if not iter.equals(self.end()):
418            k = iter.key
419            v = iter.value
420            self.erase(iter)
421            return (k, v)
422        raise KeyError(f"Key {key} not found")

Remove key and return its first key-value tuple or raise KeyError.

Args: key: Key to remove.

Example::

m = TreeMap([[1, "A"], [2, "B"], [3, "C"]])
m.popitem(2)  # "(2,B)", m is now {1:A,3:C}
m.popitem(9)  # raises KeyError
def backwards(self) -> 'PyReverseIterator[K]':
428    def backwards(self) -> PyReverseIterator[K]:
429        """
430        Return a reverse iterator over keys in descending key order (including duplicates).
431
432        Example::
433
434            m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
435            for key in m.backwards():
436                print(key)
437            # 2
438            # 2
439            # 1
440
441        """
442        return self._t.keys().backwards()

Return a reverse iterator over keys in descending key order (including duplicates).

Example::

m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
for key in m.backwards():
    print(key)
# 2
# 2
# 1
def begin(self) -> 'TreeIterator[K, V]':
481    def begin(self) -> TreeIterator[K, V]:
482        """
483        Return a forward STL-like iterator to the first entry.
484
485        Example::
486
487            m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
488            it = m.begin()
489            while not it.equals(m.end()):
490                print(f"key: {it.key}, value: {it.value}")
491                it.next()
492            # key: 1, value: A
493            # key: 2, value: B
494            # key: 2, value: C
495
496        """
497        return self._t.begin()

Return a forward STL-like iterator to the first entry.

Example::

m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
it = m.begin()
while not it.equals(m.end()):
    print(f"key: {it.key}, value: {it.value}")
    it.next()
# key: 1, value: A
# key: 2, value: B
# key: 2, value: C
def end(self) -> 'TreeIterator[K, V]':
499    def end(self) -> TreeIterator[K, V]:
500        """
501        Return a forward STL-like iterator past the last entry.
502
503        Example::
504
505            m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
506            it = m.begin()
507            while not it.equals(m.end()):
508                print(f"key: {it.key}, value: {it.value}")
509                it.next()
510
511        """
512        return self._t.end()

Return a forward STL-like iterator past the last entry.

Example::

m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
it = m.begin()
while not it.equals(m.end()):
    print(f"key: {it.key}, value: {it.value}")
    it.next()
def find(self, key: 'K') -> 'TreeIterator[K, V]':
514    def find(self, key: K) -> TreeIterator[K, V]:
515        """
516        Return a forward iterator to the first entry with *key*, or end() if absent.
517
518        When multiple entries share the same key, the iterator points to the first one.
519        Use lower_bound() / upper_bound() to iterate over all entries with that key.
520
521        Example::
522
523            m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
524            it = m.find(2)
525            if not it.equals(m.end()):
526                print(f"key: {it.key}, value: {it.value}")  # key: 2, value: B
527            m.find(99).equals(m.end())  # True
528
529        """
530        return self._t.find(key)

Return a forward iterator to the first entry with key, or end() if absent.

When multiple entries share the same key, the iterator points to the first one. Use lower_bound() / upper_bound() to iterate over all entries with that key.

Example::

m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
it = m.find(2)
if not it.equals(m.end()):
    print(f"key: {it.key}, value: {it.value}")  # key: 2, value: B
m.find(99).equals(m.end())  # True
def insert_unique(self, key: 'K', value: 'V') -> 'InsertionResult[TreeIterator[K, V]]':
532    def insert_unique(self, key: K, value: V) -> InsertionResult[TreeIterator[K, V]]:
533        """
534        Insert *(key, value)* only when *key* is not already present.
535
536        Returns:
537            InsertionResult with was_added=True when the key was new;
538            was_added=False when any entry with that key already existed.
539
540        Example::
541
542            m = TreeMultiMap()
543            res = m.insert_unique(1, "A")
544            res.was_added  # True
545            res2 = m.insert_unique(1, "B")
546            res2.was_added  # False — key 1 already exists
547
548        """
549        n: TreeNode[K, V] = TreeNode()
550        n.key = key
551        n.value = value
552        return self._t.insert_unique(n)

Insert (key, value) only when key is not already present.

Returns: InsertionResult with was_added=True when the key was new; was_added=False when any entry with that key already existed.

Example::

m = TreeMultiMap()
res = m.insert_unique(1, "A")
res.was_added  # True
res2 = m.insert_unique(1, "B")
res2.was_added  # False — key 1 already exists
def insert_or_replace(self, key: 'K', value: 'V') -> 'InsertionResult[TreeIterator[K, V]]':
554    def insert_or_replace(self, key: K, value: V) -> InsertionResult[TreeIterator[K, V]]:
555        """
556        Insert *(key, value)*, replacing the first existing entry when *key* already exists.
557
558        Returns:
559            InsertionResult with was_added=True on new insertion, or
560            was_replaced=True and the updated iterator on replacement.
561
562        Example::
563
564            m = TreeMultiMap()
565            res = m.insert_or_replace(1, "A")
566            res.was_added  # True
567            res2 = m.insert_or_replace(1, "B")
568            res2.was_replaced  # True
569            res2.iterator.value  # "B"
570
571        """
572        n: TreeNode[K, V] = TreeNode()
573        n.key = key
574        n.value = value
575        return self._t.insert_or_replace(n)

Insert (key, value), replacing the first existing entry when key already exists.

Returns: InsertionResult with was_added=True on new insertion, or was_replaced=True and the updated iterator on replacement.

Example::

m = TreeMultiMap()
res = m.insert_or_replace(1, "A")
res.was_added  # True
res2 = m.insert_or_replace(1, "B")
res2.was_replaced  # True
res2.iterator.value  # "B"
def insert_multi(self, key: 'K', value: 'V') -> 'InsertionResult[TreeIterator[K, V]]':
577    def insert_multi(self, key: K, value: V) -> InsertionResult[TreeIterator[K, V]]:
578        """
579        Insert *(key, value)* unconditionally, always creating a new entry.
580
581        This is the multi-key insertion that makes TreeMultiMap distinct from TreeMap.
582
583        Returns:
584            InsertionResult with was_added=True and an iterator to the new entry.
585
586        Example::
587
588            m = TreeMultiMap()
589            res = m.insert_multi(1, "A")
590            res.was_added  # True
591            res2 = m.insert_multi(1, "B")
592            res2.was_added  # True — second entry with key 1 added
593            res2.iterator.prev()
594            res2.iterator.value  # "A"
595
596        """
597        n: TreeNode[K, V] = TreeNode()
598        n.key = key
599        n.value = value
600        return self._t.insert_multi(n)

Insert (key, value) unconditionally, always creating a new entry.

This is the multi-key insertion that makes TreeMultiMap distinct from TreeMap.

Returns: InsertionResult with was_added=True and an iterator to the new entry.

Example::

m = TreeMultiMap()
res = m.insert_multi(1, "A")
res.was_added  # True
res2 = m.insert_multi(1, "B")
res2.was_added  # True — second entry with key 1 added
res2.iterator.prev()
res2.iterator.value  # "A"
def erase(self, iterator: 'TreeIterator[K, V]') -> None:
602    def erase(self, iterator: TreeIterator[K, V]) -> None:
603        """
604        Remove the entry pointed to by *iterator*.
605
606        Example::
607
608            m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
609            it = m.find(2)
610            m.erase(it)
611            str(m)  # "{1:A,2:C}"
612
613        """
614        self._t.erase(iterator.node)

Remove the entry pointed to by iterator.

Example::

m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
it = m.find(2)
m.erase(it)
str(m)  # "{1:A,2:C}"
def lower_bound(self, key: 'K') -> 'TreeIterator[K, V]':
616    def lower_bound(self, key: K) -> TreeIterator[K, V]:
617        """
618        Return an STL-like iterator to the first entry with key >= *key*, or end().
619
620        Combined with upper_bound(), this gives a half-open range over all
621        entries that share the same key.
622
623        Example::
624
625            m = TreeMultiMap([[2, "B1"], [2, "B2"], [4, "D"]])
626            lo = m.lower_bound(2)
627            hi = m.upper_bound(2)
628            it = lo
629            while not it.equals(hi):
630                print(it.value)  # B1, B2
631                it.next()
632
633        """
634        return self._t.lower_bound(key)

Return an STL-like iterator to the first entry with key >= key, or end().

Combined with upper_bound(), this gives a half-open range over all entries that share the same key.

Example::

m = TreeMultiMap([[2, "B1"], [2, "B2"], [4, "D"]])
lo = m.lower_bound(2)
hi = m.upper_bound(2)
it = lo
while not it.equals(hi):
    print(it.value)  # B1, B2
    it.next()
def rbegin(self) -> 'ReverseIterator[K, V]':
636    def rbegin(self) -> ReverseIterator[K, V]:
637        """
638        Return a reverse STL-like iterator to the entry with the largest key.
639
640        Example::
641
642            m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
643            it = m.rbegin()
644            while not it.equals(m.rend()):
645                print(f"key: {it.key}, value: {it.value}")
646                it.next()
647            # key: 2, value: C
648            # key: 2, value: B
649            # key: 1, value: A
650
651        """
652        return self._t.rbegin()

Return a reverse STL-like iterator to the entry with the largest key.

Example::

m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
it = m.rbegin()
while not it.equals(m.rend()):
    print(f"key: {it.key}, value: {it.value}")
    it.next()
# key: 2, value: C
# key: 2, value: B
# key: 1, value: A
def rend(self) -> 'ReverseIterator[K, V]':
654    def rend(self) -> ReverseIterator[K, V]:
655        """
656        Return a reverse STL-like iterator before the entry with the smallest key.
657
658        Example::
659
660            m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
661            it = m.rbegin()
662            while not it.equals(m.rend()):
663                print(f"key: {it.key}, value: {it.value}")
664                it.next()
665
666        """
667        return self._t.rend()

Return a reverse STL-like iterator before the entry with the smallest key.

Example::

m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
it = m.rbegin()
while not it.equals(m.rend()):
    print(f"key: {it.key}, value: {it.value}")
    it.next()
def upper_bound(self, key: 'K') -> 'TreeIterator[K, V]':
669    def upper_bound(self, key: K) -> TreeIterator[K, V]:
670        """
671        Return an STL-like iterator to the first entry with key > *key*, or end().
672
673        Combined with lower_bound(), this gives a half-open range over all
674        entries that share the same key.
675
676        Example::
677
678            m = TreeMultiMap([[2, "B1"], [2, "B2"], [4, "D"]])
679            lo = m.lower_bound(2)
680            hi = m.upper_bound(2)
681            it = lo
682            while not it.equals(hi):
683                print(it.value)  # B1, B2
684                it.next()
685
686        """
687        return self._t.upper_bound(key)

Return an STL-like iterator to the first entry with key > key, or end().

Combined with lower_bound(), this gives a half-open range over all entries that share the same key.

Example::

m = TreeMultiMap([[2, "B1"], [2, "B2"], [4, "D"]])
lo = m.lower_bound(2)
hi = m.upper_bound(2)
it = lo
while not it.equals(hi):
    print(it.value)  # B1, B2
    it.next()
def first(self) -> 'tuple[K, V] | None':
689    def first(self) -> tuple[K, V] | None:
690        """
691        Return the first (key, value) pair, or None when the map is empty.
692
693        Example::
694
695            m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
696            key, value = m.first()  # (1, "A")
697            TreeMultiMap().first()  # None
698
699        """
700        return self._t.first()

Return the first (key, value) pair, or None when the map is empty.

Example::

m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
key, value = m.first()  # (1, "A")
TreeMultiMap().first()  # None
def last(self) -> 'tuple[K, V] | None':
702    def last(self) -> tuple[K, V] | None:
703        """
704        Return the last (key, value) pair, or None when the map is empty.
705
706        Example::
707
708            m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
709            key, value = m.last()  # (2, "C")
710            TreeMultiMap().last()  # None
711
712        """
713        return self._t.last()

Return the last (key, value) pair, or None when the map is empty.

Example::

m = TreeMultiMap([[1, "A"], [2, "B"], [2, "C"]])
key, value = m.last()  # (2, "C")
TreeMultiMap().last()  # None