Entfernen und Extrahieren doppelter Elemente aus einer Liste (Array) in Python

Geschäft

Dieser Abschnitt beschreibt, wie man in Python eine neue Liste erzeugt, indem man doppelte Elemente aus einer Liste (Array) entfernt oder extrahiert.

Die folgenden Details werden hier beschrieben.

  • Entfernen doppelter Elemente und Erstellen neuer Listen
    • Die Reihenfolge der ursprünglichen Auflistung wird nicht beibehalten.:set()
    • Behält die Reihenfolge der ursprünglichen Auflistung bei: dict.fromkeys(),sorted()
    • Zweidimensionales Array (Liste von Listen)
  • Extrahieren doppelter Elemente und Erstellen einer neuen Liste
    • Die Reihenfolge der ursprünglichen Auflistung wird nicht beibehalten.
    • Behält die Reihenfolge der ursprünglichen Auflistung bei
    • Zweidimensionales Array (Liste von Listen)

Dasselbe Konzept kann auf Tupel anstelle von Listen angewendet werden.

Siehe den folgenden Artikel für

  • Wenn Sie feststellen wollen, ob eine Liste oder ein Tupel doppelte Elemente enthält
  • Wenn Sie Elemente extrahieren möchten, die bei mehreren Angeboten gemeinsam oder nicht gemeinsam sind, anstatt ein einzelnes Angebot zu wählen

Beachten Sie, dass Listen verschiedene Datentypen speichern können und sich streng von Arrays unterscheiden. Wenn Sie Arrays in Prozessen behandeln wollen, die Speichergröße und Speicheradressen oder numerische Verarbeitung großer Daten erfordern, verwenden Sie array (Standardbibliothek) oder NumPy.

Entfernen doppelter Elemente und Erstellen neuer Listen

Die Reihenfolge der ursprünglichen Auflistung wird nicht beibehalten.: set()

Wenn es nicht notwendig ist, die Reihenfolge der ursprünglichen Liste beizubehalten, verwenden Sie set(), das eine Menge vom Typ set erzeugt.

Der Typ set ist ein Datentyp, der keine doppelten Elemente hat. Wenn eine Liste oder ein anderer Datentyp an set() übergeben wird, werden doppelte Werte ignoriert, und es wird ein Objekt vom Typ set zurückgegeben, in dem nur eindeutige Werte Elemente sind.

Wenn Sie daraus ein Tupel machen wollen, verwenden Sie tuple().

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

print(set(l))
# {1, 2, 3, 4, 5}

print(list(set(l)))
# [1, 2, 3, 4, 5]

Natürlich kann er auch als Set belassen werden. Im folgenden Artikel finden Sie weitere Informationen über den Satztyp set.

Behält die Reihenfolge der ursprünglichen Auflistung bei: dict.fromkeys(),sorted()

Wenn Sie die Reihenfolge der ursprünglichen Liste beibehalten wollen, verwenden Sie die Klassenmethode fromkeys() des Typs dictionary oder die eingebaute Funktion sorted().

dict.fromkeys() erzeugt ein neues Wörterbuchobjekt, dessen Schlüssel die in den Argumenten angegebenen Listen, Tupel usw. sind. Wenn das zweite Argument weggelassen wird, ist der Wert None.

Da Wörterbuchschlüssel keine doppelten Elemente haben, werden doppelte Werte wie bei set() ignoriert. Darüber hinaus kann ein Wörterbuchobjekt als Argument an list() übergeben werden, um eine Liste zu erhalten, deren Elemente Wörterbuchschlüssel sind.

print(dict.fromkeys(l))
# {3: None, 2: None, 1: None, 5: None, 4: None}

print(list(dict.fromkeys(l)))
# [3, 2, 1, 5, 4]

Seit Python 3.7 (CPython ist 3.6) ist gewährleistet, dass dict.fromkeys() die Reihenfolge der Argumente beibehält. Frühere Versionen verwenden die eingebaute Funktion sorted() wie folgt.

Geben Sie die Listentupelmethode index() für das Argument key von sorted an, die eine sortierte Liste von Elementen zurückgibt.

index() ist eine Methode, die den Index des Wertes (die Nummer des Elements in der Liste) zurückgibt, der als Schlüssel von sorted() angegeben werden kann, um die Liste auf der Grundlage der Reihenfolge der ursprünglichen Liste zu sortieren. Das Argument key wird als aufrufbares (callable) Objekt angegeben, schreiben Sie also nicht ().

print(sorted(set(l), key=l.index))
# [3, 2, 1, 5, 4]

Zweidimensionales Array (Liste von Listen)

Bei zweidimensionalen Arrays (Listen von Listen) führt die Methode mit set() oder dict.fromkeys() zu einem TypeError.

l_2d = [[1, 1], [0, 1], [0, 1], [0, 0], [1, 0], [1, 1], [1, 1]]

# l_2d_unique = list(set(l_2d))
# TypeError: unhashable type: 'list'

# l_2d_unique_order = dict.fromkeys(l_2d)
# TypeError: unhashable type: 'list'

Dies liegt daran, dass nicht zerlegbare Objekte wie Listen keine Elemente vom Typ set oder Schlüssel vom Typ dict sein können.

Definieren Sie die folgenden Funktionen Die Reihenfolge der ursprünglichen Liste bleibt erhalten und funktioniert für eindimensionale Listen und Tupel.

def get_unique_list(seq):
    seen = []
    return [x for x in seq if x not in seen and not seen.append(x)]

print(get_unique_list(l_2d))
# [[1, 1], [0, 1], [0, 0], [1, 0]]

print(get_unique_list(l))
# [3, 2, 1, 5, 4]

Es wird die Notation des Listenverständnisses verwendet.

Hier verwenden wir Folgendes

  • Wenn X in “X und Y” bei der Kurzschlussauswertung des Operators and falsch ist, dann wird Y nicht ausgewertet (nicht ausgeführt).
  • Die Methode append() gibt keine zurück.

Wenn die Elemente der ursprünglichen Liste seq im seen nicht vorhanden sind, werden then und after ausgewertet.
seen.append(x) wird ausgeführt, und das Element wird zu seen hinzugefügt.
Da die append()-Methode None zurückgibt und None False ist, ergibt not seen.append(x) den Wert True.
Der bedingte Ausdruck in der Listenverstehensschreibweise wird zu True und wird als Element der endgültigen Liste hinzugefügt.

Wenn die Elemente der ursprünglichen Liste seq in seen vorhanden sind, dann ist x not in seen False, und der bedingte Ausdruck für den Listenverstehensausdruck ist False.
Sie werden daher nicht als Elemente in die endgültige Liste aufgenommen.

Eine andere Methode besteht darin, das Argument axis in der NumPy-Funktion np.unique() zu setzen, obwohl das Ergebnis sortiert wird.

Extrahieren doppelter Elemente und Erstellen einer neuen Liste

Die Reihenfolge der ursprünglichen Auflistung wird nicht beibehalten.

Um nur doppelte Elemente aus der ursprünglichen Liste zu extrahieren, verwenden Sie collections.Counter().
Gibt einen collections.Counter (eine Unterklasse von dictionary) mit den Elementen als Schlüssel und der Anzahl der Elemente als Wert zurück.

import collections

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

print(collections.Counter(l))
# Counter({3: 3, 2: 2, 1: 2, 5: 1, 4: 1})

Da es sich um eine Unterklasse von dictionary handelt, kann items() zum Abrufen von Schlüsseln und Werten verwendet werden. Es reicht aus, Schlüssel zu extrahieren, deren Anzahl zwei oder mehr beträgt.

print([k for k, v in collections.Counter(l).items() if v > 1])
# [3, 2, 1]

Behält die Reihenfolge der ursprünglichen Auflistung bei

Wie im obigen Beispiel gezeigt, behalten die Schlüssel von collections.Counter seit Python 3.7 die Reihenfolge der ursprünglichen Liste bei usw.

In früheren Versionen ist das Sortieren mit sorted() ausreichend, ebenso wie das Löschen von doppelten Elementen.

print(sorted([k for k, v in collections.Counter(l).items() if v > 1], key=l.index))
# [3, 2, 1]

Wenn Sie Duplikate extrahieren möchten, lassen Sie einfach Elemente mit einer Nummer von zwei oder mehr aus der ursprünglichen Liste übrig. Die Reihenfolge bleibt ebenfalls erhalten.

cc = collections.Counter(l)
print([x for x in l if cc[x] > 1])
# [3, 3, 2, 1, 1, 2, 3]

Zweidimensionales Array (Liste von Listen)

Für zweidimensionale Arrays (Listen von Listen) sind die folgenden Funktionen möglich, wenn die Reihenfolge der ursprünglichen Liste nicht beibehalten wird bzw. wenn sie beibehalten wird. Sie funktionieren auch für eindimensionale Listen und Tupel.

l_2d = [[1, 1], [0, 1], [0, 1], [0, 0], [1, 0], [1, 1], [1, 1]]
def get_duplicate_list(seq):
    seen = []
    return [x for x in seq if not seen.append(x) and seen.count(x) == 2]

def get_duplicate_list_order(seq):
    seen = []
    return [x for x in seq if seq.count(x) > 1 and not seen.append(x) and seen.count(x) == 1]

print(get_duplicate_list(l_2d))
# [[0, 1], [1, 1]]

print(get_duplicate_list_order(l_2d))
# [[1, 1], [0, 1]]

print(get_duplicate_list(l))
# [3, 1, 2]

print(get_duplicate_list_order(l))
# [3, 2, 1]

Wenn Sie mit Duplikaten extrahieren wollen, lassen Sie Elemente aus der ursprünglichen Liste mit einer Anzahl von zwei oder mehr.

print([x for x in l_2d if l_2d.count(x) > 1])
# [[1, 1], [0, 1], [0, 1], [1, 1], [1, 1]]

Da die Rechenkomplexität von count() O(n) ist, ist die oben gezeigte Funktion, die count() wiederholt ausführt, sehr ineffizient. Vielleicht gibt es einen intelligenteren Weg.

Counter ist eine Unterklasse von dictionary. Wenn Sie also eine Liste oder ein Tupel, dessen Elemente Listen oder andere nicht hashbare Objekte sind, an collections.Counter() übergeben, tritt ein Fehler auf und Sie können es nicht verwenden.

# print(collections.Counter(l_2d))
# TypeError: unhashable type: 'list'