Python Mengen (set und frozenset)           (C) 2020-2025 T.Birnthaler OSTC GmbH
=================================

Doku --> docs.python.org/3/library/stdtypes.html#set

Mengen (set und frozenset) speichern jedes ELEMENT nur 1x, d.h.
mehrfache Vorkommen des gleichen Elements sind nicht möglich.

  s1 = set()    oder   s1 = set({})       # Leere Menge (NICHT {} = leeres dict)
  s2 = {"abc", True, 123, -3.14, (1,2,3)} # 5 Elemente
  s3 = {1, 2, 3}                          # 3 Elemente
  s4 = {1, 2, 3, 1, 2, 3, 4, 1}           # 4 Elemente {1, 2, 3, 4}

* ELEMENTE sind UNIQUE (d.h. das gleiche ELEMENT kann nur 1x vorkommen).

* ELEMENTE müssen IM-MUTABLE Objekte bzw. eigentlich HASHABLE Objekte sein
  (NoneType, bool, int, float, complex, str, tuple, frozenset, bytes).

* Die ZUGRIFFSGESCHWINDIGKEIT auf ein bestimmtes ELEMENT (in Menge enthalten
  oder nicht) ist UN-ABHÄNGIG von der Größe der Menge immer gleich SCHNELL
  (RANDOM ACCESS).

* Die ELEMENTE in einem Set sind UN-GEORDNET. Will man einen Zugriff in
  spezieller Reihenfolge, muss man beim Zugriff MANUELL sortieren.

* Eine Menge lässt sich als "degeneriertes" Dictionary betrachten,
  bei dem zum KEY der VALUE fehlt (Element = Key).

* Die LEERE Menge muss per set() oder set({}) erzeugt werden, nicht per {}.

Von Sets (mutable) + Frozensets (im-mutable) unterstützte Operationen
(S, T sind Sets, E ist ein Element):

ACHTUNG: Nur LESENDE Operationen, das Set S bleibt UNVERÄNDERT!

+--------------------+------------------------------------------------+
| for E in S: ...    | Alle Elemente E von S durchlaufen (ungeordnet) |
+--------------------+------------------------------------------------+
| E in S             | Ist Element E in S enthalten?                  |
| E not in S         | Ist Element E in S nicht enthalten?            |
+--------------------+------------------------------------------------+
| len(S)             | Anzahl Elemente                                |
| T = S.copy()       | Shallow/Flache Kopie                           |
+--------------------+------+--------+--------------------------------+
|                           | S == T | Mengen gleich?                 |
|                           | S != T | Mengen ungleich?               |
+---------------------------+--------+--------------------------------+
| S.isdisjoint(T)           |        | Schnittmenge leer?             |
| S.issubset(T)             | S <= T | Ist Teilmenge (unecht)?        |
|                           | S < T  | Ist echte Teilmenge?           |
| S.issuperset(T)           | S >= T | Ist Obermenge (unecht)?        |
|                           | S > T  | Ist echte Obermenge?           |
+---------------------------+--------+--------------------------------+
| S.union(T)                | S | T  | Vereinigungsmenge bilden       |
| S.intersection(T)         | S & T  | Schnittmenge bilden            |
| S.difference(T)           | S - T  | Differenzmenge bilden          |
| S.symmetric_difference(T) | S ^ T  | Symmetrische Differenzmenge b. |
+---------------------------+--------+--------------------------------+

Nur von Sets (mutable) unterstützte Operationen
(S, T sind Sets, E ist ein Element):

ACHTUNG: SCHREIBENDE Operationen,
         die Menge S wird VERÄNDERT (bleibt aber das gleiche Objekt)!

ACHTUNG: Die Operationen |= &= -= ^= sind auch auf Frozenset anwendbar,
         erzeugen aber einen NEUEN Frozenset!

+----------------------------------+-------------------------------------------+
| S.add(E)                         | Element hinzufügen                        |
| S.remove(E)                      | Element entfernen (oder KeyError)         |
| S.discard(E)                     | Element entfernen (KEIN KeyError)         |
| S.pop()                          | Belieb. El. entfernen + zurück (KeyError) |
+----------------------------------+--------+----------------------------------+
| S.update(T)                      | S |= T | Vereinigungsmenge zuweisen       |
| S.intersection_update(T)         | S &= T | Schnittmenge zuweisen            |
| S.difference_update(T)           | S -= T | Differenzmenge zuweisen          |
| S.symmetric_difference_update(T) | S ^= T | Symmetrische Differenzmenge zuw. |
+----------------------------------+--------+----------------------------------+
| S.clear()                        | Set leeren (alle Elemente entfernen)      |
+----------------------------------+-------------------------------------------+

HINWEIS: Zugriff auf eine Menge mit einem nicht vorhandenen Element löst
         die Exception "KeyError" aus.

HINWEIS: Seit Python 3.7 entspricht die Element-Reihenfolge im Set der
Einfüge-Reihenfolge und bleibt bei Operationen auf dem Set erhalten. Vorher war
die Reihenfolge der Elemente ZUFÄLLIG und konnte sich jederzeit ändern.

HINWEIS: Die Elemente "True/False" in Sets werden mit den Elementen 1/0 (int),
1.0/0.0 (float) und 1+0j/0+0j (complex) IDENTIFIZIERT, da sie den gleichen
HASH-Wert haben (d.h. jedes der Elemente kann nur 1x in einem Set vorkommen).

  True  <--> 1 <--> 1.0 <--> 1+0.0j <--> 1+0j
  False <--> 0 <--> 0.0 <--> 0+0.0j <--> 0+0j

Vor PY3.7 war das ein ZUFÄLLIGES Element, seit PY3.7 ist es das ERSTE im Set
vorkommende Element.

  S = { True, 1, 1.0, 1+0j }    # --> {True}
  S = { 1+0j, 1.0, 1, True }    # --> {0+0j}
  S = { False, 0, 0.0, 0+0j }   # --> {False}
  S = { 0+0j, 0.0, 0, False }   # --> {0+0j}