Eliminarea și extragerea elementelor duplicate dintr-o listă (array) în Python

Afaceri

Această secțiune descrie modul de generare a unei noi liste în Python prin eliminarea sau extragerea elementelor duplicate dintr-o listă (array).

Aici sunt descrise următoarele detalii.

  • Eliminați elementele duplicate și generați liste noi
    • Nu păstrați ordinea din lista inițială:set()
    • Păstrează ordinea din lista inițială: dict.fromkeys(),sorted()
    • Matrice bidimensională (listă de liste)
  • Extragerea elementelor duplicate și generarea unei noi liste
    • Nu păstrați ordinea din lista inițială
    • Păstrează ordinea din lista inițială
    • Matrice bidimensională (listă de liste)

Același concept poate fi aplicat la tuple în loc de liste.

A se vedea următorul articol pentru

  • Dacă doriți să determinați dacă o listă sau un tuple are elemente duplicate
  • Dacă doriți să extrageți elemente care sunt comune sau nu între mai multe liste în loc de o singură listă

Rețineți că listele pot stoca diferite tipuri de date și sunt strict diferite de array-uri. Dacă doriți să manipulați array-uri în procese care necesită dimensiunea memoriei și adrese de memorie sau procesarea numerică a unor date mari, utilizați array (biblioteca standard) sau NumPy.

Eliminați elementele duplicate și generați liste noi

Nu păstrați ordinea din lista inițială: set()

Dacă nu este necesar să se păstreze ordinea din lista originală, utilizați set(), care generează un set de tip set.

Tipul set este un tip de date care nu are elemente duplicate. Atunci când o listă sau un alt tip de date este transmis la set(), valorile duplicate sunt ignorate și se returnează un obiect de tip set în care numai valorile unice sunt elemente.

Dacă doriți să o transformați într-un tupluplu, utilizați 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]

Bineînțeles, poate fi lăsată și așa cum a fost stabilită. Consultați următorul articol pentru mai multe informații despre tipul de set set.

Păstrează ordinea din lista inițială: dict.fromkeys(),sorted()

Dacă doriți să păstrați ordinea din lista originală, utilizați metoda de clasă fromkeys() a tipului dicționar sau funcția încorporată sorted().

dict.fromkeys() creează un nou obiect dicționar ale cărui chei sunt listele, tuplurile etc. specificate în argumente. În cazul în care al doilea argument este omis, valoarea este None.

Deoarece cheile de dicționar nu au elemente duplicate, valorile duplicate sunt ignorate ca în set(). În plus, un obiect de dicționar poate fi trecut ca argument la list() pentru a obține o listă ale cărei elemente sunt chei de dicționar.

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

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

Începând cu Python 3.7 (CPython este 3.6), este garantat faptul că dict.fromkeys() păstrează ordinea secvenței de argumente. Versiunile anterioare utilizează funcția încorporată sorted() după cum urmează.

Precizați metoda index() a tuploanelor de liste pentru argumentul key din sorted, care returnează o listă de elemente sortate.

index() este o metodă care returnează indexul valorii (numărul elementului din listă), care poate fi specificat ca cheie a metodei sorted() pentru a sorta lista pe baza ordinii din lista originală. Argumentul key este specificat ca obiect apelabil (callable), deci nu scrieți ().

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

Matrice bidimensională (listă de liste)

Pentru array-urile bidimensionale (liste de liste), metoda care utilizează set() sau dict.fromkeys() generează o eroare de tip 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'

Acest lucru se datorează faptului că obiectele care nu pot fi șahate, cum ar fi listele, nu pot fi elemente de tip set sau chei de tip dict.

Definiți următoarele funcții Ordinea listei originale este păstrată și funcționează pentru liste unidimensionale și tuple.

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]

Se utilizează notația de înțelegere a listei.

Aici, folosim următoarele

  • Dacă X din „X și Y” este fals în evaluarea în scurtcircuit a operatorului and, atunci Y nu este evaluat (nu este executat).
  • Metoda append() returnează None.

În cazul în care elementele din lista originală seq nu există în lista văzută, atunci și după sunt evaluate.
seen.append(x) este executat și elementul este adăugat la seen.
Deoarece metoda append() returnează None și None este False, nu seen.append(x) se evaluează la True.
Expresia condițională din notația de înțelegere a listei devine True și este adăugată ca element al listei finale generate.

Dacă elementele din lista originală seq sunt prezente în seen, atunci x care nu se află în seen este False, iar expresia condițională pentru expresia de înțelegere a listei este False.
Prin urmare, acestea nu sunt adăugate ca elemente ale listei finale generate.

O altă metodă este de a seta axa argumentului în funcția NumPy np.unique(), deși rezultatul va fi sortat.

Extragerea elementelor duplicate și generarea unei noi liste

Nu păstrați ordinea din lista inițială

Pentru a extrage numai elementele duplicate din lista originală, utilizați collections.Counter().
Returnează un collections.Counter (o subclasă a dicționarului) cu elementele ca chei și numărul de elemente ca valori.

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

Deoarece este o subclasă de dicționar, items() poate fi utilizat pentru a prelua chei și valori. Este suficient pentru a extrage cheile al căror număr este de două sau mai multe.

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

Păstrează ordinea din lista inițială

După cum se arată în exemplul de mai sus, începând cu Python 3.7, cheile din collections.Counter păstrează ordinea din lista originală și așa mai departe.

În versiunile anterioare, sortarea cu sorted() este suficientă, la fel ca și ștergerea elementelor duplicate.

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

Dacă doriți să extrageți duplicatele așa cum sunt, lăsați pur și simplu elementele din lista originală cu un număr de doi sau mai mulți. Ordinea este, de asemenea, păstrată.

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

Matrice bidimensională (listă de liste)

Pentru array-urile bidimensionale (liste de liste), următoarele funcții sunt posibile atunci când ordinea din lista originală nu este păstrată și, respectiv, atunci când este păstrată. De asemenea, funcționează și pentru liste unidimensionale și tupluri.

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]

Dacă doriți să extrageți cu duplicate, lăsați elementele din lista originală cu un număr de două sau mai multe.

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

Rețineți că, deoarece complexitatea de calcul a count() este O(n), funcția prezentată mai sus care execută în mod repetat count() este foarte ineficientă. Este posibil să existe o modalitate mai inteligentă.

Counter este o subclasă a dicționarului, astfel încât, dacă treceți o listă sau un tupluplu ale cărui elemente sunt liste sau alte obiecte care nu pot fi șahate la collections.Counter(), se va produce o eroare și nu veți putea să o utilizați.

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