Fjern og uddrag dobbelte elementer fra en liste (array) i Python

Forretning

Dette afsnit beskriver, hvordan du genererer en ny liste i Python ved at fjerne eller udtrække dobbelte elementer fra en liste (array).

Følgende oplysninger beskrives her.

  • Fjern dublerede elementer og generer nye lister
    • Bevar ikke rækkefølgen i den oprindelige liste:set()
    • Bevarer rækkefølgen i den oprindelige liste: dict.fromkeys(),sorted()
    • To-dimensionalt array (liste af lister)
  • Udtrække dobbelte elementer og generere en ny liste
    • Bevar ikke rækkefølgen i den oprindelige liste
    • Bevarer rækkefølgen i den oprindelige liste
    • To-dimensionalt array (liste af lister)

Det samme koncept kan anvendes på tupler i stedet for lister.

Se følgende artikel om

  • Hvis du vil bestemme, om en liste eller tupel har dobbelte elementer
  • Hvis du ønsker at udtrække elementer, der er fælles eller ikke fælles for flere opslag i stedet for et enkelt opslag

Bemærk, at lister kan lagre forskellige typer data og er helt forskellige fra arrays. Hvis du ønsker at håndtere arrays i processer, der kræver hukommelsesstørrelse og hukommelsesadresser eller numerisk behandling af store data, skal du bruge array (standardbiblioteket) eller NumPy.

Fjern dublerede elementer og generer nye lister

Bevar ikke rækkefølgen i den oprindelige liste: set()

Hvis der ikke er behov for at bevare rækkefølgen af den oprindelige liste, kan du bruge set(), som genererer et sæt af typen set.

Sættetypen er en datatype, der ikke har nogen dubletter. Når en liste eller en anden datatype overføres til set(), ignoreres duplikerede værdier, og der returneres et objekt af typen set, hvor kun unikke værdier er elementer.

Hvis du ønsker at gøre det til en tuple, skal du bruge 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]

Den kan naturligvis også stå som den er indstillet. Se følgende artikel for flere oplysninger om sæt-typen set.

Bevarer rækkefølgen i den oprindelige liste: dict.fromkeys(),sorted()

Hvis du vil bevare rækkefølgen i den oprindelige liste, skal du bruge klassemetoden fromkeys() for ordbogstypen eller den indbyggede funktion sorted().

dict.fromkeys() opretter et nyt ordbogsobjekt, hvis nøgler er de lister, tupler osv., der er angivet i argumenterne. Hvis det andet argument er udeladt, er værdien None.

Da ordbogsnøgler ikke har duplikerede elementer, ignoreres duplikerede værdier som i set(). Desuden kan et ordbogsobjekt overføres som et argument til list() for at få en liste, hvis elementer er ordbogsnøgler.

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

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

Siden Python 3.7 (CPython er 3.6) har det været garanteret, at dict.fromkeys() bevarer rækkefølgen af argumentsekvensen. Tidligere versioner bruger den indbyggede funktion sorted() på følgende måde.

Angiv listens tupelmetode index() for argumentet key for sorted, som returnerer en sorteret liste af elementer.

index() er en metode, der returnerer indekset for værdien (nummeret på elementet i listen), som kan angives som nøgle for sorted() for at sortere listen i henhold til rækkefølgen i den oprindelige liste. Argumentet key angives som et objekt, der kan kaldes (callable), så skriv ikke ().

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

To-dimensionalt array (liste af lister)

For todimensionale arrays (lister af lister) resulterer metoden, der anvender set() eller dict.fromkeys(), i en 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'

Det skyldes, at ikke-hashbare objekter som f.eks. lister ikke kan være elementer af typen set eller nøgler af typen dict.

Definer følgende funktioner Ordningen i den oprindelige liste bevares og fungerer for endimensionale lister og tupler.

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]

Der anvendes listeforståelsesnotation.

Her anvender vi følgende

  • Hvis X i “X og Y” er falsk i kortslutningsevalueringen af and-operatoren, evalueres Y ikke (udføres ikke).
  • Metoden append() returnerer ingen.

Hvis elementerne i den oprindelige liste seq ikke findes i seen, evalueres derefter og efter.
seen.append(x) udføres, og elementet tilføjes til seen.
Da append()-metoden returnerer None og None er False, evalueres ikke seen.append(x) til True.
Det betingede udtryk i listeforståelsesnotationen bliver sandt og tilføjes som et element i den endelige genererede liste.

Hvis elementerne i den oprindelige liste seq findes i seen, er x, der ikke findes i seen, False, og det betingede udtryk for listeforståelsesudtrykket er False.
Derfor tilføjes de ikke som elementer i den endelige genererede liste.

En anden metode er at indstille argumentet akse i NumPys funktion np.unique(), selv om resultatet vil blive sorteret.

Udtrække dobbelte elementer og generere en ny liste

Bevar ikke rækkefølgen i den oprindelige liste

Hvis du kun vil udtrække duplikerede elementer fra den oprindelige liste, skal du bruge collections.Counter().
Returnerer en collections.Counter (en underklasse af dictionary) med elementerne som nøgler og antallet af elementer som værdier.

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 det er en underklasse af dictionary, kan items() bruges til at hente nøgler og værdier. Det er tilstrækkeligt at udtrække nøgler, hvis antal er to eller flere.

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

Bevarer rækkefølgen i den oprindelige liste

Som vist i eksemplet ovenfor har nøglerne i collections.Counter siden Python 3.7 beholdt rækkefølgen i den oprindelige liste osv.

I tidligere versioner er det tilstrækkeligt at sortere med sorted(), ligesom det er tilstrækkeligt at slette dobbelte elementer.

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

Hvis du ønsker at udtrække dubletter, som de er, skal du blot lade elementer fra den oprindelige liste med et nummer på to eller flere stå tilbage. Rækkefølgen bevares også.

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

To-dimensionalt array (liste af lister)

For todimensionale arrays (lister af lister) er følgende funktioner mulige, henholdsvis når rækkefølgen af den oprindelige liste ikke er bevaret og når den er bevaret. Det virker også for endimensionale lister og tupler.

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]

Hvis du vil udtrække med dubletter, skal du efterlade elementer fra den oprindelige liste med et antal på to eller flere.

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

Bemærk, at eftersom beregningskompleksiteten af count() er O(n), er den ovenfor viste funktion, der gentagne gange udfører count(), meget ineffektiv. Der findes måske en smartere måde.

Counter er en underklasse af dictionary, så hvis du sender en liste eller tupel, hvis elementer er lister eller andre ikke-hashbare objekter, til collections.Counter(), vil der opstå en fejl, og du vil ikke kunne bruge den.

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