Pythonische Methode zum Erstellen einer Vereinigung aller in mehreren Listen enthaltenen Werte

80

Ich habe eine Liste von Listen:

lists = [[1,4,3,2,4], [4,5]]

Ich möchte diese Liste reduzieren und alle Duplikate entfernen. oder mit anderen Worten, wenden Sie eine festgelegte Vereinigungsoperation an:

desired_result = [1, 2, 3, 4, 5]

Was ist der einfachste Weg, dies zu tun?

AJ.
quelle

Antworten:

144

set.union macht was du willst:

>>> results_list = [[1,2,3], [1,2,4]]
>>> results_union = set().union(*results_list)
>>> print(results_union)
set([1, 2, 3, 4])

Sie können dies auch mit mehr als zwei Listen tun.

etw
quelle
@sth, danke zum Beispiel, aber wenn ich es ausführe, erhalte ich eine Fehlermeldung: Traceback (letzter Aufruf zuletzt): Datei "so_example.py", Zeile 33, in? results_union = set (). union (* result_lists) TypeError: union () akzeptiert genau ein Argument (3 angegeben)
AJ.
1
@AJ: Gemäß der Dokumentation ( docs.python.org/library/stdtypes.html#set.union ) werden union()nur mehrere Argumente für Python Version 2.6 oder höher unterstützt. Sie scheinen vorher eine Version zu verwenden, daher müssen Sie wahrscheinlich eine explizite Schleife verwenden: total = set(); for x in results_list: total.update(x) (s /; / \ n /)
etw
2
Sie können das Erstellen eines leeren Satzes auch speichern, indem Sie die 2. Zeile inresults_union = set.union(*(set(el) for el in results_list))
Noel Evans
1
@ Jean-FrançoisFabre TypeError: descriptor 'union' requires a 'set' object but received a 'list'in Python 3.6 mindestens.
Paritosh Singh
1
Wenn Sie verwenden set.union(*results_list), binden Sie den Methodendeskriptor manuell, dh senden Sie das erste Element results_listals "self" ein. Dies macht einige seltsame Einschränkungen: 1. Ententyp nicht richtig (jetzt muss das erste Element eine Menge oder Instanz einer Mengenunterklasse sein), und 2. Die Vereinigung eines Leerzeichens results_listist ein Fehler (falsches Ergebnis - sollte leer zurückgeben einstellen).
wim
11

Da Sie anscheinend Python 2.5 verwenden (es wäre schön, in Ihrem Q zu erwähnen, wenn Sie ein A für Versionen benötigen! = 2.6, übrigens die aktuelle Produktion ;-) und eine Liste anstelle eines Sets als das wollen Ergebnis empfehle ich:

import itertools

...

return list(set(itertools.chain(*result_list)))

itertools ist im Allgemeinen eine großartige Möglichkeit, mit Iteratoren (und damit mit vielen Arten von Sequenzen oder Sammlungen) zu arbeiten, und ich empfehle Ihnen von Herzen, sich damit vertraut zu machen. itertools.chaininsbesondere ist hier dokumentiert .

Alex Martelli
quelle
+1 Ein perfektes Beispiel für eine gute Zeit, um in das wundervolle itertoolsPaket einzutauchen.
Gotgenes
@Alex danke ... habe meine Frage bearbeitet, um die Version anzugeben und mir die Schuld dafür zu nehmen, dass ich in Versionen so zurückgeblieben bin :) Ich werde es mir zum Ziel setzen, in itertools zu schauen, den Vorschlag zu schätzen.
AJ.
@AJ, keine Schuld, wir alle können schließlich unter solchen Einschränkungen leiden (aber bitte denken Sie daran, in zukünftigen Qs anzugeben! -); itertools.chainfunktioniert übrigens auch in Python 2.4 einwandfrei.
Alex Martelli
3

Sie können diesem Stil auch folgen

In [12]: a = ['Orange and Banana', 'Orange Banana']
In [13]: b = ['Grapes', 'Orange Banana']
In [14]: c = ['Foobanana', 'Orange and Banana']

In [20]: list(set(a) | set(b) | set(c))
Out[20]: ['Orange and Banana', 'Foobanana', 'Orange Banana', 'Grapes']

In [21]: list(set(a) & set(b) | set(c))
Out[21]: ['Orange and Banana', 'Foobanana', 'Orange Banana']    
GrvTyagi
quelle
1

Gewerkschaften werden nicht von Listen unterstützt, die geordnet sind, sondern von Gruppen. Schauen Sie sich set.union an .

Justin R.
quelle
0

Ich habe das Folgende verwendet, um Schnittpunkte zu erstellen, wodurch die Notwendigkeit von Mengen vermieden wird.

a, b= [[1,2,3], [1,2]]
s = filter( lambda x: x in b, a)

oder,

s = [ x for x in b if x in a ]
Bär
quelle
5
Warum sollten Sie überhaupt "die Notwendigkeit von Sets vermeiden" wollen? Zu diesem Zweck sind sie schneller und klarer. Und Ihr "x in a" führt bei jeder Ausführung eine lineare Brute-Force-Suche in der Liste durch. Yuck.
Peter Hansen
Sätze erfordern Typ Casting, und die lineare Geschwindigkeit ist nicht schlecht, es sei denn, Sie haben es mit einem großen N zu tun.
Bear
3
"Typguss"? In Python? Seit wann? Sets sind im Grunde genommen Diktate mit nur den Schlüsseln und sie verwenden Hash- und Gleichheitsvergleiche. Die Verwendung von "x in a" in einer Liste führt auch einen Gleichheitsvergleich durch. Was ist das alles über Typ Casting?
Peter Hansen
0

verständnisvoll:

[*{ j for i in lists for j in i }]

oder

[*functools.reduce(lambda x,y: {*x, *y}, lists)]
Geil
quelle
-2
desired_result = [x for y in lists for x in y]
Mike G.
quelle