Liste zum Einstellen hinzufügen?

242

Getestet mit Python 2.6 Interpreter:

>>> a=set('abcde')
>>> a
set(['a', 'c', 'b', 'e', 'd'])
>>> l=['f','g']
>>> l
['f', 'g']
>>> a.add(l)
Traceback (most recent call last):
  File "<pyshell#35>", line 1, in <module>
    a.add(l)
TypeError: list objects are unhashable

Ich denke, dass ich die Liste nicht zum Set hinzufügen kann, da Python nicht erkennen kann, ob ich dieselbe Liste zweimal hinzugefügt habe. Gibt es eine Problemumgehung?

EDIT: Ich möchte die Liste selbst hinzufügen, nicht ihre Elemente.

Adam Matan
quelle
2
Möchten Sie die Liste zum Set oder zu den Elementen in der Liste hinzufügen?
pkit
Die Liste selbst - Ich möchte eine Reihe von Listen haben.
Adam Matan
Die am besten geeignete Antwort scheint die unterschätzte zu sein. Sie schlägt vor, aSet.add (id (lst)) zu verwenden, bevor Sie lst selbst zu einer Liste / Warteschlange / usw. hinzufügen, um sicherzugehen, dass Sie es getan haben. Sie sollten die akzeptierte Antwort überdenken.
Rustam A.

Antworten:

187

Sie können einer Gruppe keine Liste hinzufügen, da Listen veränderbar sind. Dies bedeutet, dass Sie den Inhalt der Liste ändern können, nachdem Sie sie der Gruppe hinzugefügt haben.

Sie können dem Set jedoch Tupel hinzufügen, da Sie den Inhalt eines Tupels nicht ändern können:

>>> a.add(('f', 'g'))
>>> print a
set(['a', 'c', 'b', 'e', 'd', ('f', 'g')])

Bearbeiten : einige Erklärungen: In der Dokumentation wird a setals ungeordnete Sammlung unterschiedlicher hashbarer Objekte definiert. Die Objekte müssen hashbar sein, damit das Suchen, Hinzufügen und Entfernen von Elementen bei jeder Ausführung dieser Vorgänge schneller erfolgen kann als das Betrachten jedes einzelnen Elements. Die spezifischen verwendeten Algorithmen werden im Wikipedia-Artikel erläutert . Pythons-Hashing-Algorithmen werden auf effbot.org erklärt und Pythons __hash__funktionieren in der Python-Referenz .

Einige Fakten:

  • Set-Elemente sowie Wörterbuchschlüssel müssen hashbar sein
  • Einige nicht zerlegbare Datentypen:
    • list: tuplestattdessen verwenden
    • set: frozensetstattdessen verwenden
    • dict: hat kein offizielles Gegenstück, aber es gibt einige Rezepte
  • Objektinstanzen können standardmäßig gehasht werden, wobei jede Instanz einen eindeutigen Hash hat. Sie können dieses Verhalten überschreiben, wie in der Python-Referenz erläutert.
Otto Allmendinger
quelle
6
Und wenn Sie jemals ein Set zu einem Set hinzufügen möchten, verwenden Sie frozenset.
FogleBird
4
collections.namedtuplekönnte als "offizielles" Gegenstück zum dict.
SilentGhost
1
@Wahnfrieden: Das heißt, der Inhalt eines Sets wird hinzugefügt , nicht das Set selbst.
Otto Allmendinger
@aehlke: Nein, das fügt die Elemente der Menge der ersten Menge hinzu, aber wir sprechen über das Hinzufügen einer Menge als Element der ersten Menge.
Jeff Learman
578

Verwenden Sie set.update()oder|=

>>> a = set('abc')
>>> l = ['d', 'e']
>>> a.update(l)
>>> a
{'e', 'b', 'c', 'd', 'a'}

>>> l = ['f', 'g']
>>> a |= set(l)
>>> a
{'e', 'b', 'f', 'c', 'd', 'g', 'a'}

Bearbeiten: Wenn Sie die Liste selbst und nicht ihre Mitglieder hinzufügen möchten, müssen Sie leider ein Tupel verwenden. Festgelegte Mitglieder müssen hashbar sein .

aehlke
quelle
set.update () fügt die Liste dem Set hinzu, richtig? Wofür ist der Pipe Equals Operator?
FistOfFury
In Bezug auf die Mengen, der |implementiert Bediener die Vereinigungsoperation . Sowohl der |=Operator als auch die set.update()Methode wenden diese Operation direkt an und sind praktisch synonym. Könnte set_a |= set_balso als syntaktischer Zucker für beide set_a.update(set_b) und betrachtet werden set_a = set_a | set_b (außer dass im letzteren Fall dasselbe set_aObjekt wiederverwendet und nicht neu zugewiesen wird). </ahem>
Cecil Curry
76

Um die Elemente einer Liste zu einem Satz hinzuzufügen , verwendetupdate

Von https://docs.python.org/2/library/sets.html

s.update (t): Rückgabesatz s mit Elementen, die aus t hinzugefügt wurden

Z.B

>>> s = set([1, 2])
>>> l = [3, 4]
>>> s.update(l)
>>> s
{1, 2, 3, 4}

Wenn Sie stattdessen die gesamte Liste als einzelnes Element zum Satz hinzufügen möchten , können Sie dies nicht, da Listen nicht hashbar sind. Sie können stattdessen ein Tupel hinzufügen, z s.add(tuple(l)). Weitere Informationen hierzu finden Sie unter TypeError: unhashable type: 'list' bei Verwendung der integrierten Set-Funktion .

JDiMatteo
quelle
40

Hoffentlich hilft das:

>>> seta = set('1234')
>>> listb = ['a','b','c']
>>> seta.union(listb)
set(['a', 'c', 'b', '1', '3', '2', '4'])
>>> seta
set(['1', '3', '2', '4'])
>>> seta = seta.union(listb)
>>> seta
set(['a', 'c', 'b', '1', '3', '2', '4'])
Alvas
quelle
15

Bitte beachten Sie die Funktion set.update(). Die Dokumentation sagt:

Aktualisieren Sie ein Set mit der Vereinigung von sich selbst und anderen.

Eierfliege
quelle
5
Dies beantwortet die Frage nicht (da das OP die Liste selbst zum Set hinzufügen möchte), aber es war die Antwort, die ich brauchte, als Google mich hierher brachte :-)
Tom Stratton
1
Nun, es scheint mir die relevanteste Antwort auf die Frage zu sein ... Wenn zum Beispiel b = set ([1]), gibt b.update ([7,25]) b den folgenden Wert: set ([ 1, 25, 7]) ---> Ist es nicht das, wonach wir hier suchen?
Louis LC
8

Listenobjekte können nicht verwertet werden . Vielleicht möchten Sie sie jedoch in Tupel umwandeln.

SilentGhost
quelle
5

Sets können keine veränderlichen (veränderbaren) Elemente / Elemente haben. Eine Liste, die veränderlich ist, kann kein Mitglied einer Gruppe sein.

Da Sets veränderlich sind, können Sie keine Sets haben! Sie können jedoch eine Reihe von Frozensets haben.

(Die gleiche Art von "Veränderbarkeitsanforderung" gilt für die Schlüssel eines Diktats.)

Andere Antworten haben Ihnen bereits Code gegeben, ich hoffe, dies gibt ein wenig Einblick. Ich hoffe, Alex Martelli wird mit noch mehr Details antworten.

user135331
quelle
4

Sie möchten ein Tupel hinzufügen, keine Liste:

>>> a=set('abcde')
>>> a
set(['a', 'c', 'b', 'e', 'd'])
>>> l=['f','g']
>>> l
['f', 'g']
>>> t = tuple(l)
>>> t
('f', 'g')
>>> a.add(t)
>>> a
set(['a', 'c', 'b', 'e', 'd', ('f', 'g')])

Wenn Sie eine Liste haben, können Sie wie oben gezeigt in das Tupel konvertieren. Ein Tupel ist unveränderlich und kann daher dem Satz hinzugefügt werden.

hughdbrown
quelle
4

Ich stellte fest, dass ich heute etwas Ähnliches tun musste. Der Algorithmus wusste, wann eine neue Liste erstellt wurde, die dem Satz hinzugefügt werden musste, aber nicht, wann die Bearbeitung der Liste beendet worden wäre.

Wie auch immer, das Verhalten, das ich wollte, war eher für die Verwendung idals für das Set hash. Als solches fand ich, mydict[id(mylist)] = mylistanstatt myset.add(mylist)das Verhalten anzubieten, das ich wollte.

Dünen
quelle
3

Sie sollten Tupel verwenden, die hashbar sind (Sie können ein veränderbares Objekt wie eine Liste nicht hashen).

>>> a = set("abcde")
>>> a
set(['a', 'c', 'b', 'e', 'd'])
>>> t = ('f', 'g')
>>> a.add(t)
>>> a
set(['a', 'c', 'b', 'e', 'd', ('f', 'g')])
Noah
quelle
2

So mache ich es normalerweise:

def add_list_to_set(my_list, my_set):
    [my_set.add(each) for each in my_list]
return my_set
kashif
quelle
-4

Dies sollte tun:

set(tuple(i) for i in L)
WQS
quelle