Python entfernen Set aus Set

74

Gemäß meiner Interpretation der Python 2.7.2-Dokumentation für integrierte Typen 5.7 Set-Typen sollte es möglich sein, die Elemente von Set A aus Set B zu entfernen, indem A an set.remove(elem)oder übergeben wirdset.discard(elem)

Aus der Dokumentation zu 2.7.2:

Beachten Sie , dass das Elem Argument der __contains__(), remove()und discard() Methoden kann ein Satz sein.

Ich interpretiere dies so, dass ich ein setan remove(elem)oder übergeben kann discard(elem)und alle diese Elemente aus dem Zielsatz entfernt werden. Ich würde dies verwenden, um etwas Seltsames zu tun, wie alle Vokale aus einer Zeichenfolge zu entfernen oder alle gebräuchlichen Wörter aus einem Worthäufigkeitshistogramm zu entfernen . Hier ist der Testcode:

Python 2.7.2 (default, Jun 12 2011, 14:24:46) [M...
Type "help", "copyright", "credits" or "license"
>>> a = set(range(10))
>>> b = set(range(5,10))
>>> a
set([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> b
set([8, 9, 5, 6, 7])
>>> a.remove(b)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: set([8, 9, 5, 6, 7])
>>> a.discard(b)
>>> a
set([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>>

Was ich voraussichtlich wiederkommen werde:

>>> a
set([0, 1, 2, 3, 4])

Ich weiß, dass ich dies erreichen kann, a.difference(b)wodurch ein neuer Satz zurückgegeben wird. oder mit einem set.difference_update(other); oder mit Set-Operatoren a -= b, die das Set an Ort und Stelle ändern.

Ist das also ein Fehler in der Dokumentation? Kann man set.remove(elem)eigentlich keinen Satz als Argument nehmen? Oder bezieht sich die Dokumentation auf Sätze von Sätzen? Angesichts der Tatsache, dass difference_updatedies meine Interpretation erfüllt, ist der Fall vermutlich der letztere.

Ist das unklar genug?

BEARBEITEN Nach 3 Jahren zusätzlicher (professioneller) Python-Arbeit und nachdem ich kürzlich auf diese Frage zurückgegriffen habe, stelle ich jetzt fest, dass das, was ich eigentlich versucht habe, erreicht werden kann mit:

>>> c = a.difference(b)
set([0,1,2,3,4])

Das ist es, was ich ursprünglich versucht habe zu bekommen.

BEARBEITEN Nach 4 weiteren Jahren Python-Entwicklung ... ist mir klar, dass diese Operation mit festgelegten Literalen und dem -Operator sauberer ausgedrückt werden kann . und dass es vollständiger ist zu zeigen, dass die eingestellte Differenz nicht kommutativ ist.

>>> a={0,1,2,3}
>>> b={2,3,4,5}
>>> a-b
set([0, 1])
>>> b-a
set([4, 5])
cod3monk3y
quelle
c = a.difference(b)funktioniert bei mir. Vielen Dank!
Gihanchanuka

Antworten:

21

Sie haben die Frage bereits beantwortet. Es bezieht sich auf Sätze von Sätzen (tatsächlich Sätze, die Frozensets enthalten).

Der Absatz, auf den Sie sich beziehen, beginnt mit:

Beachten Sie, dass das Argument elem für die Methoden __contains __ (), remove () und discard () eine Menge sein kann.

was bedeutet, dass bin a.remove(b)eine Menge sein kann und dann fortfährt mit:

Um die Suche nach einem äquivalenten Frozenset zu unterstützen , wird das Element-Set während der Suche vorübergehend mutiert und dann wiederhergestellt. Während der Suche sollte das Element-Set nicht gelesen oder mutiert werden, da es keinen aussagekräftigen Wert hat.

Das bedeutet , dass , wenn bein Satz ist, a.remove(b)scannt aeine frozenset entspricht bund abnehmen (oder einen Wurf , KeyErrorwenn es nicht vorhanden ist).

Nitsas
quelle
Vielen Dank! Angesichts meiner Fehlinterpretation ergab dieser zweite Satz wenig Sinn. Dies als primäre Antwort zu wählen, da es hilft, mein primäres Missverständnis zu klären. Lings Beispiel war auch sehr hilfreich.
cod3monk3y
12

set1-set2

set1={0,1,2,3}
set2={2,3,4,5}

set1-set2
# {0, 1}
set2-set1
# {4, 5}
Nic Scozzaro
quelle
2
Endlich eine einfache Antwort!
Andrei Margeloiu
8

Sie können in Python kein sets von sets haben, da a setveränderlich ist. Stattdessen können Sie sets von frozensets haben. Auf der anderen Seite, können Sie anrufen __contains__(), remove()und discard()mit ein set. Siehe dieses Beispiel:

a = set([frozenset([2])])
set([2]) in a       # you get True
a.remove(set([2]))  # a is now empty

Die Antwort auf Ihre Frage lautet also, dass sich die Dokumentation auf sets von frozensets bezieht .

Ling
quelle
Sehr schöne, prägnante Darstellung dessen, was für mich ein ungewöhnlich unklarer Teil der Python-Dokumentation ist. Danke Ling!
cod3monk3y
2

Ich schaue mir die eingebaute Hilfe für verschiedene Versionen von Python (für Mac) an. Hier sind die Ergebnisse.

  • python2.5

entfernen (...)
Ein Element aus einer Menge entfernen; es muss ein Mitglied sein.
Wenn das Element kein Mitglied ist, lösen Sie einen KeyError aus.

  • python2.6

entfernen (...)
Ein Element aus einer Menge entfernen; es muss ein Mitglied sein. Wenn das Element kein Mitglied ist, lösen Sie einen KeyError aus.

  • python2.7

entfernen (...)
Ein Element aus einer Menge entfernen; es muss ein Mitglied sein. Wenn das Element kein Mitglied ist, lösen Sie einen KeyError aus.

In der Dokumentation, auf die Sie sich vollständig beziehen, heißt es tatsächlich:

Beachten Sie , dass das Elem Argument der __contains__(), remove()und discard()Methoden kann ein Satz sein. Um die Suche nach einem äquivalenten Frozenset zu unterstützen, wird das Element-Set während der Suche vorübergehend mutiert und dann wiederhergestellt.

Dies scheint eine Fußnote zu sein, die darauf hindeutet, dass das Argument eine Menge sein kann. Wenn es jedoch keine passende eingefrorene Menge innerhalb der Menge findet, wird es nicht entfernt. Die Erwähnung über das zu ändernde Set ist so, dass es gehasht werden kann, um nach einem passenden eingefrorenen Set zu suchen.

Josh Smeaton
quelle
1

Ich denke, die Dokumentation bezieht sich auf Sätze von (eingefrorenen) Sätzen, ja.

Bernstein
quelle
2
Aber Sie können keine Sätze haben; Sets sind nicht hashbar. Sie könnten ein Set mit einem Frozenset als Element haben, denke ich.
DSM
2
@DSM - daher wird in der Dokumentation der elemWert erwähnt, der während des Aufrufs mutiert wird, um festzustellen , ob es ein Äquivalent gibt frozenset.
Amber