Zestaw Union of 2 nie zawiera wszystkich elementów

94

Jak to się dzieje, że kiedy zmieniam kolejność dwóch zestawów w poniższych złączach, otrzymuję różne wyniki?

set1 = {1, 2, 3}
set2 = {True, False}

print(set1 | set2)
# {False, 1, 2, 3}

print(set2 | set1)
#{False, True, 2, 3}
Blueplastic
źródło

Odpowiedzi:

110

Dlaczego union () nie zawiera wszystkich elementów

Elementy 1i Truesą równoważne i uważane za duplikaty. Podobnie 0i Falsesą również równoważne:

>>> 1 == True
True
>>> 0 == False
True

Która równoważna wartość jest używana

W przypadku napotkania wielu równoważnych wartości zestawy zachowują pierwszą widoczną:

>>> {0, False}
{0}
>>> {False, 0}
{False}

Sposoby wyróżniania wartości

Aby traktować je jako odrębne, po prostu zapisz je w (value, type)parze:

>>> set1 = {(1, int), (2, int), (3, int)}
>>> set2 = {(True, bool), (False, bool)}
>>> set1 | set2
{(3, <class 'int'>), (1, <class 'int'>), (2, <class 'int'>),
 (True, <class 'bool'>), (False, <class 'bool'>)}
>>> set1 & set2
set()

Innym sposobem na odróżnienie wartości jest przechowywanie ich jako ciągów:

>>> set1 = {'1', '2', '3'}
>>> set2 = {'True', 'False'}
>>> set1 | set2
{'2', '3', 'False', 'True', '1'}
>>> set1 & set2
set()

Mam nadzieję, że to wyjaśnia tajemnicę i wskazuje drogę naprzód :-)


Uratowany z komentarzy:

Jest to standardowa technika łamania krzyżowych równoważności (tj 0.0 == 0, True == 1iDecimal(8.5) == 8.5) . Technika ta jest stosowana w zwykły moduł ekspresyjny Python 2,7 do regexes siła unikodzie na buforowane wyraźnie od równoważna regexes str. Technika ta jest również stosowana w Pythonie 3 dla functools.lru_cache (), gdy wpisany parametr ma wartość true.

Jeśli PO potrzebuje czegoś innego niż domyślna relacja równoważności, należy zdefiniować nową relację. W zależności od przypadku użycia, może to być niewrażliwość na wielkość liter dla ciągów znaków, normalizacja dla Unicode, wygląd wizualny (rzeczy, które wyglądają inaczej są uważane za różne), tożsamość (żadne dwa różne obiekty nie są uważane za równe), para wartość / typ lub inne funkcja definiująca relację równoważności. Biorąc pod uwagę konkretny przykład PO, wydaje się, że spodziewał się on rozróżnienia według typu lub wizualnego.

Raymond Hettinger
źródło
20

W Pythonie Falsei 0są uważane za równoważne, podobnie jak Truei 1. Ponieważ Truei 1są uważane za tę samą wartość, tylko jeden z nich może występować w zestawie w tym samym czasie. Który z nich zależy od kolejności, w jakiej są one dodawane do zestawu. W pierwszej linii set1jest używany jako pierwszy zestaw, więc otrzymujemy 1wynikowy zestaw. W drugim zestawie Trueznajduje się w pierwszym zestawie, więc Truejest uwzględniany w wyniku.

mcslane
źródło
6

Jeśli spojrzysz na https://docs.python.org/3/library/stdtypes.html#boolean-values sekcja 4.12.10. Wartości logiczne:

Wartości logiczne to dwa stałe obiekty False i True . Służą do reprezentowania wartości prawdy (chociaż inne wartości można również uznać za fałszywe lub prawdziwe). W kontekstach liczbowych (na przykład, gdy są używane jako argument operatora arytmetycznego), zachowują się jak odpowiednio liczby całkowite 0 i 1 .

chocksaway
źródło
4

Operator porównania ( ==, !=) jest zdefiniowany dla wartości logicznych TrueiFalse dopasowany do 1 i 0.

Dlatego w set union, gdy sprawdza, czy Truejest już w nowym zestawie, otrzymuje prawdziwą odpowiedź:

>>> True in {1}
True
>>> 1 in {True}
True
Uriel
źródło