Odstránenie a extrahovanie duplicitných prvkov zo zoznamu (poľa) v jazyku Python

obchodné

Táto časť opisuje, ako v jazyku Python vytvoriť nový zoznam odstránením alebo vyňatím duplicitných prvkov zo zoznamu (poľa).

Sú tu opísané tieto podrobnosti.

  • Odstránenie duplicitných prvkov a generovanie nových zoznamov
    • Nezachovávajte poradie pôvodného zoznamu:set()
    • Zachováva poradie pôvodného zoznamu: dict.fromkeys(),sorted()
    • Dvojrozmerné pole (zoznam zoznamov)
  • Výber duplicitných prvkov a vytvorenie nového zoznamu
    • Nezachovávajte poradie pôvodného zoznamu
    • Zachováva poradie pôvodného zoznamu
    • Dvojrozmerné pole (zoznam zoznamov)

Rovnaký koncept sa dá použiť aj na tuply namiesto zoznamov.

Pozrite si nasledujúci článok

  • Ak chcete zistiť, či má zoznam alebo tuple duplicitné prvky
  • Ak chcete namiesto jedného výpisu extrahovať prvky, ktoré sú spoločné alebo nie sú spoločné pre viacero výpisov

Všimnite si, že zoznamy môžu uchovávať rôzne typy údajov a striktne sa líšia od polí. Ak chcete pracovať s poliami v procesoch, ktoré vyžadujú veľkosť pamäte a pamäťové adresy alebo numerické spracovanie veľkých dát, použite array (štandardná knižnica) alebo NumPy.

Odstránenie duplicitných prvkov a generovanie nových zoznamov

Nezachovávajte poradie pôvodného zoznamu: set()

Ak nie je potrebné zachovať poradie pôvodného zoznamu, použite funkciu set(), ktorá vygeneruje množinu typu set.

Typ množiny je dátový typ, ktorý nemá duplicitné prvky. Keď sa funkcii set() odovzdá zoznam alebo iný dátový typ, duplicitné hodnoty sa ignorujú a vráti sa objekt typu set, ktorého prvkami sú len jedinečné hodnoty.

Ak chcete vytvoriť tuple, použite funkciu 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]

Samozrejme, možno ho ponechať aj v nastavenom stave. Viac informácií o type set nájdete v nasledujúcom článku.

Zachováva poradie pôvodného zoznamu: dict.fromkeys(),sorted()

Ak chcete zachovať poradie pôvodného zoznamu, použite metódu triedy fromkeys() typu dictionary alebo vstavanú funkciu sorted().

dict.fromkeys() vytvorí nový objekt slovníka, ktorého kľúčmi sú zoznamy, tuply atď. zadané v argumentoch. Ak je druhý argument vynechaný, hodnota je None.

Keďže kľúče slovníka nemajú duplicitné prvky, duplicitné hodnoty sa ignorujú rovnako ako v funkcii set(). Okrem toho možno objekt slovníka odovzdať ako argument funkcii list() a získať tak zoznam, ktorého prvky sú kľúče slovníka.

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

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

Od verzie Python 3.7 (CPython je 3.6) je zaručené, že funkcia dict.fromkeys() zachováva poradie argumentov. Skoršie verzie používajú vstavanú funkciu sorted() nasledovne.

Pre argument key of sorted zadajte metódu index(), ktorá vráti zoradený zoznam prvkov.

index() je metóda, ktorá vracia index hodnoty (číslo prvku v zozname), ktorý môže byť zadaný ako kľúč metódy sorted() na zoradenie zoznamu na základe poradia pôvodného zoznamu. Argument kľúč sa zadáva ako volateľný (calllable) objekt, preto nepíšte ().

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

Dvojrozmerné pole (zoznam zoznamov)

V prípade dvojrozmerných polí (zoznamov zoznamov) metóda používajúca set() alebo dict.fromkeys() vedie k 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'

Je to preto, že objekty, ktoré nie sú shashovateľné, ako napríklad zoznamy, nemôžu byť prvkami typu set alebo kľúčmi typu dict.

Definujte nasledujúce funkcie Poradie pôvodného zoznamu je zachované a funguje pre jednorozmerné zoznamy a tuply.

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]

Používa sa notácia na porozumenie zoznamu.

Tu používame tieto údaje

  • Ak je X v „X a Y“ nepravdivé pri skrátenom vyhodnotení operátora a, potom sa Y nevyhodnotí (nevykoná).
  • Metóda append() vracia hodnotu None.

Ak prvky pôvodného zoznamu seq neexistujú vo videnom, potom sa vyhodnotí a after.
vykoná sa seen.append(x) a prvok sa pridá do seen.
Keďže metóda append() vracia None a None je False, not seen.append(x) sa vyhodnotí ako True.
Podmienený výraz v zápise porozumenia zoznamu sa stane pravdivým a pridá sa ako prvok konečného vygenerovaného zoznamu.

Ak sú prvky pôvodného zoznamu seq prítomné v zozname seen, potom x, ktoré nie je v zozname seen, je False a podmienený výraz pre výraz porozumenia zoznamu je False.
Preto sa nepridávajú ako prvky konečného vygenerovaného zoznamu.

Ďalšou metódou je nastavenie osi argumentu vo funkcii NumPy np.unique(), hoci výsledok bude zoradený.

Výber duplicitných prvkov a vytvorenie nového zoznamu

Nezachovávajte poradie pôvodného zoznamu

Ak chcete z pôvodného zoznamu vybrať len duplicitné prvky, použite funkciu collections.Counter().
Vráti súbor collections.Counter (podtrieda slovníka) s prvkami ako kľúčmi a počtom prvkov ako hodnotami.

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

Keďže ide o podtriedu slovníka, na načítanie kľúčov a hodnôt možno použiť funkciu items(). Stačí získať kľúče, ktorých počet je dva alebo viac.

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

Zachováva poradie pôvodného zoznamu

Ako je uvedené v príklade vyššie, od verzie Python 3.7 si kľúče kolekcie.Counter zachovávajú poradie pôvodného zoznamu atď.

V predchádzajúcich verziách stačí triedenie pomocou funkcie sorted(), ako aj odstraňovanie duplicitných prvkov.

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

Ak chcete vyňať duplikáty tak, ako sú, jednoducho ponechajte prvky z pôvodného zoznamu s číslom dva alebo viac. Zachová sa aj poradie.

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

Dvojrozmerné pole (zoznam zoznamov)

Pre dvojrozmerné polia (zoznamy zoznamov) sú možné nasledujúce funkcie, keď sa nezachováva poradie pôvodného zoznamu a keď sa zachováva. Funguje to aj pre jednorozmerné zoznamy a tuply.

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]

Ak chcete extrahovať s duplikátmi, ponechajte prvky z pôvodného zoznamu s počtom dva alebo viac.

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

Všimnite si, že keďže výpočtová zložitosť funkcie count() je O(n), vyššie uvedená funkcia, ktorá opakovane vykonáva count(), je veľmi neefektívna. Môže existovať inteligentnejší spôsob.

Čítač je podtriedou slovníka, takže ak funkcii collections.Counter() odovzdáte zoznam alebo tuple, ktorého prvky sú zoznamy alebo iné objekty, ktoré sa nedajú hashovať, dôjde k chybe a nebude možné ju použiť.

# print(collections.Counter(l_2d))
# TypeError: unhashable type: 'list'
Copied title and URL