Selles jaotises kirjeldatakse, kuidas luua Pythonis uus nimekiri, eemaldades või eemaldades loetelust (massiivi) dubleerivaid elemente.
Siin on kirjeldatud järgmisi üksikasju.
- Eemaldage dubleerivad elemendid ja genereerige uued nimekirjad
- Ärge säilitage esialgse loetelu järjekorda.:
set()
- Säilitab esialgse loetelu järjekorra:
dict.fromkeys()
,sorted()
- Kahemõõtmeline massiivi (nimekirjade nimekiri)
- Ärge säilitage esialgse loetelu järjekorda.:
- Eraldage dubleerivad elemendid ja genereerige uus nimekiri
- Ärge säilitage esialgse loetelu järjekorda.
- Säilitab esialgse loetelu järjekorra
- Kahemõõtmeline massiivi (nimekirjade nimekiri)
Sama kontseptsiooni saab rakendada loetelude asemel tuplite suhtes.
Vt järgmist artiklit
- Kui soovite kindlaks teha, kas loetelus või tuplis on dubleerivaid elemente
- Kui soovite eraldada elemendid, mis on ühised või mitte ühised mitme loeteluga, mitte ühe loeteluga
Pange tähele, et loendid võivad salvestada eri tüüpi andmeid ja erinevad rangelt massiividest. Kui soovite käsitleda massiive protsessides, mis nõuavad mälu suurust ja mäluaadressi või suurte andmete numbrilist töötlemist, kasutage array (standardraamatukogu) või NumPy.
Eemaldage dubleerivad elemendid ja genereerige uued nimekirjad
Ärge säilitage esialgse loetelu järjekorda.: set()
Kui algse loendi järjekorda ei ole vaja säilitada, kasutage funktsiooni set(), mis genereerib komplekti tüüpi komplekti.
Kogumitüüp on andmetüüp, millel ei ole dubleerivaid elemente. Kui loendi või muu andmetüüp antakse funktsioonile set(), ignoreeritakse dubleerivaid väärtusi ja tagastatakse set-tüüpi objekt, mille elementideks on ainult unikaalsed väärtused.
Kui soovite sellest tuple'i teha, kasutage 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]
Loomulikult võib selle ka nii jätta, nagu see on seatud. Lisateavet komplekstüübi set kohta leiate järgmisest artiklist.
Säilitab esialgse loetelu järjekorra: dict.fromkeys(),sorted()
Kui soovite säilitada algse loendi järjekorda, kasutage sõnastiku tüübi klassi meetodit fromkeys() või sisseehitatud funktsiooni sorted().
dict.fromkeys() loob uue sõnastikuobjekti, mille võtmed on argumentides määratud nimekirjad, tuplid jne. Kui teine argument jäetakse ära, on väärtus None.
Kuna sõnastiku võtmed ei sisalda dubleerivaid elemente, ignoreeritakse dubleerivaid väärtusi nagu set() puhul. Lisaks saab sõnastiku objekti edastada argumendina funktsioonile list(), et saada nimekiri, mille elemendid on sõnastiku võtmed.
print(dict.fromkeys(l))
# {3: None, 2: None, 1: None, 5: None, 4: None}
print(list(dict.fromkeys(l)))
# [3, 2, 1, 5, 4]
Alates Python 3.7-st (CPython on 3.6) on tagatud, et dict.fromkeys() säilitab argumentide järjestuse. Varasemad versioonid kasutavad sisseehitatud funktsiooni sorted() järgmiselt.
Määrake loenditupli meetod index() argumendi sorteeritud võtmele, mis tagastab sorteeritud elementide loendi.
index() on meetod, mis tagastab väärtuse indeksi (elemendi number loendis), mida saab määrata võtmena funktsioonile sorted(), et sorteerida loendit esialgse loendi järjekorra alusel. Argument key on määratud kutsutava (callable) objektina, seega ei tohi kirjutada ().
print(sorted(set(l), key=l.index))
# [3, 2, 1, 5, 4]
Kahemõõtmeline massiivi (nimekirjade nimekiri)
Kahemõõtmeliste massiividega (loetelude loendid) puhul annab meetod, mis kasutab set() või dict.fromkeys(), TypeError'i.
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'
Selle põhjuseks on see, et mittehashitavad objektid, nagu näiteks loetelud, ei saa olla elemendid tüübist set või võtmed tüübist dict.
Defineeri järgmised funktsioonid Esialgse loendi järjekord säilib ja see töötab ühemõõtmeliste loendite ja tuplite puhul.
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]
Kasutatakse loetelu mõistmise märkimist.
Siinkohal kasutame järgmist
- Kui X on “X ja Y” operaatori ja lühiajalisel hindamisel vale, siis Y ei hinnata (ei täideta).
- Meetod append() tagastab None.
Kui esialgse loendi seq elemente ei ole näha, siis hinnatakse ja pärast.
seen.append(x) käivitatakse ja element lisatakse seen'ile.
Kuna meetod append() tagastab None ja None on False, ei ole seen.append(x) väärtuseks True.
Loetelu mõistmise notatsioonis olev tingimusavaldis muutub tõeseks ja lisatakse lõpliku genereeritud loendi elemendiks.
Kui algse loendi seq elemendid on sees, siis x ei ole sees, siis on False ja loendi mõistmise tingimusavaldis on False.
Seetõttu ei lisata neid elementidena lõplikku genereeritud loetelusse.
Teine meetod on määrata argumendi telg NumPy funktsioonis np.unique(), kuigi tulemus on sorteeritud.
Eraldage dubleerivad elemendid ja genereerige uus nimekiri
Ärge säilitage esialgse loetelu järjekorda.
Kui soovite algsest nimekirjast välja võtta ainult dubleeritud elemendid, kasutage collections.Counter().
Tagastab collections.Counter (sõnastiku alamklass), mille võtmetena on elemendid ja väärtustena elementide arv.
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})
Kuna tegemist on sõnastiku alamklassiga, saab võtmete ja väärtuste saamiseks kasutada funktsiooni items(). Piisab võtmete väljavõttest, mille arv on kaks või rohkem.
print([k for k, v in collections.Counter(l).items() if v > 1])
# [3, 2, 1]
Säilitab esialgse loetelu järjekorra
Nagu ülaltoodud näites näidatud, säilitavad alates Python 3.7-st collections.Counter'i võtmed algse loendi järjekorra jne.
Varasemates versioonides piisab sorteerimisest funktsiooniga sorted() ja dubleeritud elementide kustutamisest.
print(sorted([k for k, v in collections.Counter(l).items() if v > 1], key=l.index))
# [3, 2, 1]
Kui soovite duplikaate sellisel kujul välja võtta, jätke lihtsalt algsest nimekirjast elemendid, mille number on kaks või rohkem. Ka järjekord säilib.
cc = collections.Counter(l)
print([x for x in l if cc[x] > 1])
# [3, 3, 2, 1, 1, 2, 3]
Kahemõõtmeline massiivi (nimekirjade nimekiri)
Kahemõõtmeliste massiividega (loetelude loendid) on võimalik kasutada järgmisi funktsioone, kui algse loendi järjekorda ei säilitata ja kui see säilitatakse. See töötab ka ühemõõtmeliste loendite ja tuplite puhul.
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]
Kui soovite ekstraheerida koos duplikaatidega, jätke algsest loendist elemendid, mille arv on kaks või rohkem.
print([x for x in l_2d if l_2d.count(x) > 1])
# [[1, 1], [0, 1], [0, 1], [1, 1], [1, 1]]
Pange tähele, et kuna count() arvutuskomplekssus on O(n), on ülaltoodud funktsioon, mis korraldab count() korduvalt, väga ebaefektiivne. Võib olla targem viis.
Counter on dictionary alamklass, nii et kui te annate collections.Counter() funktsioonile üle nimekirja või tupli, mille elemendid on nimekirjad või muud mittehashitavad objektid, tekib viga ja te ei saa seda kasutada.
# print(collections.Counter(l_2d))
# TypeError: unhashable type: 'list'