Dubbele elementen uit een lijst (array) verwijderen en extraheren in Python

Bedrijf

Dit hoofdstuk beschrijft hoe je een nieuwe lijst in Python genereert door dubbele elementen uit een lijst (array) te verwijderen of te extraheren.

De volgende details worden hier beschreven.

  • Dubbele elementen verwijderen en nieuwe lijsten genereren
    • Behoud niet de volgorde van de oorspronkelijke lijst:set()
    • Behoudt de volgorde van de oorspronkelijke vermelding: dict.fromkeys(),sorted()
    • Tweedimensionale matrix (lijst van lijsten)
  • Dubbele elementen verwijderen en een nieuwe lijst genereren
    • Behoud niet de volgorde van de oorspronkelijke lijst
    • Behoudt de volgorde van de oorspronkelijke vermelding
    • Tweedimensionale matrix (lijst van lijsten)

Hetzelfde concept kan worden toegepast op tupels in plaats van op lijsten.

Zie het volgende artikel voor

  • Als je wilt bepalen of een lijst of tupel dubbele elementen heeft
  • Als u elementen wilt extraheren die gemeenschappelijk of niet gemeenschappelijk zijn onder meerdere lijsten in plaats van een enkele lijst

Merk op dat lijsten verschillende soorten gegevens kunnen opslaan en strikt verschillend zijn van arrays. Als u arrays wilt verwerken in processen die geheugengrootte en geheugenadressen vereisen of numerieke verwerking van grote gegevens, gebruik dan array (standaardbibliotheek) of NumPy.

Dubbele elementen verwijderen en nieuwe lijsten genereren

Behoud niet de volgorde van de oorspronkelijke lijst: set()

Als het niet nodig is om de volgorde van de oorspronkelijke lijst te behouden, gebruik dan set(), die een set van het type set genereert.

Het type set is een gegevenstype dat geen dubbele elementen heeft. Wanneer een lijst of een ander gegevenstype wordt doorgegeven aan set(), worden dubbele waarden genegeerd en wordt een object van het type set teruggegeven waarin alleen unieke waarden elementen zijn.

Als je er een tuple van wilt maken, gebruik dan 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]

Natuurlijk kan het ook als set worden gelaten. Zie het volgende artikel voor meer informatie over het set type set.

Behoudt de volgorde van de oorspronkelijke vermelding: dict.fromkeys(),sorted()

Als je de volgorde van de oorspronkelijke lijst wilt behouden, gebruik dan de klassemethode fromkeys() van het type dictionary of de ingebouwde functie sorted().

dict.fromkeys() creëert een nieuw woordenboekobject waarvan de sleutels lijsten, tupels, enz. zijn die in de argumenten worden opgegeven. Indien het tweede argument wordt weggelaten, is de waarde Geen.

Aangezien woordenboeksleutels geen dubbele elementen hebben, worden dubbele waarden genegeerd zoals in set(). Bovendien kan een dictionary-object doorgegeven worden als argument aan list() om een lijst te verkrijgen waarvan de elementen dictionary-sleutels zijn.

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

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

Sinds Python 3.7 (CPython is 3.6) wordt gegarandeerd dat dict.fromkeys() de volgorde van de argumentreeks bewaart. Eerdere versies gebruiken de ingebouwde functie sorted() als volgt.

Specificeer de lijsttupelmethode index() voor het argument sleutel van sorted, die een gesorteerde lijst van elementen teruggeeft.

index() is een methode die de index van de waarde teruggeeft (het nummer van het element in de lijst), die kan worden opgegeven als de sleutel van sorted() om de lijst te sorteren op basis van de volgorde van de oorspronkelijke lijst. Het argument sleutel wordt gespecificeerd als een aanroepbaar (calllable) object, dus schrijf niet ().

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

Tweedimensionale matrix (lijst van lijsten)

Voor tweedimensionale arrays (lijsten van lijsten) resulteert de methode met set() of dict.fromkeys() in een 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'

Dat komt omdat niet-hashbare objecten zoals lijsten geen elementen van het type set of sleutels van het type dict kunnen zijn.

Definieer de volgende functies De volgorde van de oorspronkelijke lijst wordt bewaard en werkt voor eendimensionale lijsten en tupels.

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]

Er wordt een notatie voor lijstbegrip gebruikt.

Hier gebruiken we het volgende

  • Als X in “X en Y” onwaar is in de kortsluitingsevaluatie van de en operator, dan wordt Y niet geëvalueerd (niet uitgevoerd).
  • De append() methode retourneert Geen.

Als de elementen van de oorspronkelijke lijst seq niet bestaan in de gezien, dan worden en na geëvalueerd.
seen.append(x) wordt uitgevoerd en het element wordt toegevoegd aan seen.
Omdat de append() methode None teruggeeft en None is False, evalueert niet seen.append(x) naar True.
De voorwaardelijke uitdrukking in de lijstbegripnotatie wordt Waar en wordt toegevoegd als een element van de uiteindelijke gegenereerde lijst.

Als de elementen van de oorspronkelijke lijst seq aanwezig zijn in gezien, dan is x niet in gezien is False, en de voorwaardelijke uitdrukking voor de lijstbegrip is False.
Daarom worden zij niet toegevoegd als elementen van de uiteindelijke gegenereerde lijst.

Een andere methode is om het argument as in te stellen in NumPy's functie np.unique(), hoewel het resultaat dan gesorteerd zal zijn.

Dubbele elementen verwijderen en een nieuwe lijst genereren

Behoud niet de volgorde van de oorspronkelijke lijst

Om alleen dubbele elementen uit de oorspronkelijke lijst te halen, gebruik je collections.Counter().
Geeft een collections.counter (een subklasse van dictionary) terug met de elementen als sleutels en het aantal elementen als waarden.

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})

Aangezien het een subklasse van dictionary is, kan items() gebruikt worden om sleutels en waarden op te halen. Het is voldoende om sleutels op te halen waarvan het aantal twee of meer is.

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

Behoudt de volgorde van de oorspronkelijke vermelding

Zoals in het bovenstaande voorbeeld te zien is, behouden de sleutels van collections.counter sinds Python 3.7 de volgorde van de oorspronkelijke lijst, enzovoort.

In eerdere versies is sorteren met sorted() voldoende, net als het verwijderen van dubbele elementen.

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

Als u duplicaten wilt extraheren zoals ze zijn, laat u gewoon elementen uit de oorspronkelijke lijst met een nummer van twee of meer staan. De volgorde blijft ook behouden.

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

Tweedimensionale matrix (lijst van lijsten)

Voor tweedimensionale arrays (lijsten van lijsten) zijn de volgende functies mogelijk wanneer de volgorde van de oorspronkelijke lijst niet behouden blijft en wanneer dat wel het geval is. Het werkt ook voor eendimensionale lijsten en tupels.

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]

Als u wilt uitpakken met duplicaten, laat u elementen uit de oorspronkelijke lijst met een telling van twee of meer staan.

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

Merk op dat aangezien de rekenkundige complexiteit van count() O(n) is, de hierboven getoonde functie die herhaaldelijk count() uitvoert zeer inefficiënt is. Er is misschien een slimmere manier.

Teller is een subklasse van dictionary, dus als je een lijst of tuple waarvan de elementen lijsten of andere niet-hashbare objecten zijn doorgeeft aan collections.Counter(), zal er een fout optreden en zul je het niet kunnen gebruiken.

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