Ez a szakasz leírja, hogyan hozhatunk létre egy új listát Pythonban úgy, hogy eltávolítjuk vagy kivonjuk a duplikált elemeket egy listából (tömbből).
A következő részleteket ismertetjük.
- Duplikált elemek eltávolítása és új listák létrehozása
- Ne őrizze meg az eredeti felsorolás sorrendjét:
set()
- Megőrzi az eredeti lista sorrendjét:
dict.fromkeys()
,sorted()
- Kétdimenziós tömb (listák listája)
- Ne őrizze meg az eredeti felsorolás sorrendjét:
- Duplikált elemek kivonása és új lista létrehozása
- Ne őrizze meg az eredeti felsorolás sorrendjét
- Megőrzi az eredeti lista sorrendjét
- Kétdimenziós tömb (listák listája)
Ugyanez a koncepció alkalmazható a listák helyett a tuplikra is.
Lásd a következő cikket
- Ha meg akarja határozni, hogy egy lista vagy egy tuple tartalmaz-e duplikált elemeket
- Ha egyetlen listázás helyett több listázásban közös vagy nem közös elemeket szeretne kivonatolni
Vegye figyelembe, hogy a listák különböző típusú adatokat tárolhatnak, és szigorúan különböznek a tömböktől. Ha olyan folyamatokban szeretnénk tömböket kezelni, amelyek memóriaméretet és memóriacímeket vagy nagyméretű adatok numerikus feldolgozását igénylik, használjuk a array (standard könyvtár) vagy a NumPy programot.
Duplikált elemek eltávolítása és új listák létrehozása
Ne őrizze meg az eredeti felsorolás sorrendjét: set()
Ha nincs szükség az eredeti lista sorrendjének megőrzésére, használjuk a set() funkciót, amely egy set típusú set-et generál.
A halmaz típus olyan adattípus, amelynek nincsenek duplikált elemei. Ha egy listát vagy más adattípust adunk át a set() függvénynek, a duplikált értékeket figyelmen kívül hagyjuk, és egy olyan set típusú objektumot kapunk vissza, amelyben csak egyedi értékek az elemek.
Ha tuple-t akarsz belőle csinálni, használd a tuple() funkciót.
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]
Természetesen meghagyható úgy is, ahogy van beállítva. A set típusról bővebben a következő cikkben olvashat a set típusról.
Megőrzi az eredeti lista sorrendjét: dict.fromkeys(),sorted()
Ha meg akarja őrizni az eredeti lista sorrendjét, használja a szótár típus fromkeys() osztálymódszerét vagy a beépített sorted() függvényt.
A dict.fromkeys() egy új szótár objektumot hoz létre, amelynek kulcsai az argumentumokban megadott listák, tuplik stb. Ha a második argumentum kimarad, az érték None.
Mivel a szótárkulcsok nem tartalmaznak duplikált elemeket, a duplikált értékek figyelmen kívül maradnak, mint a set() esetében. Ezen kívül egy szótár objektumot átadhatunk argumentumként a list()-nak, hogy egy olyan listát kapjunk, amelynek elemei szótári kulcsok.
print(dict.fromkeys(l))
# {3: None, 2: None, 1: None, 5: None, 4: None}
print(list(dict.fromkeys(l)))
# [3, 2, 1, 5, 4]
A Python 3.7 óta (a CPython 3.6-os) garantált, hogy a dict.fromkeys() megőrzi az argumentumok sorrendjét. A korábbi verziók a beépített sorted() függvényt használják a következőképpen.
Adja meg a listatömbök index() metódusát a sorted argumentum kulcsához, amely az elemek rendezett listáját adja vissza.
Az index() egy olyan metódus, amely visszaadja az érték indexét (a lista elemének számát), amelyet a sorted() kulcsaként adhatunk meg, hogy a listát az eredeti lista sorrendje alapján rendezzük. A kulcs argumentumot hívható (callable) objektumként adjuk meg, tehát ne írjuk ki ().
print(sorted(set(l), key=l.index))
# [3, 2, 1, 5, 4]
Kétdimenziós tömb (listák listája)
Kétdimenziós tömbök (listák listái) esetén a set() vagy a dict.fromkeys() módszer TypeError-t eredményez.
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'
Ennek az az oka, hogy az olyan nem-kapcsolt objektumok, mint a listák, nem lehetnek set típusú elemek vagy dict típusú kulcsok.
Definiálja a következő függvényeket Az eredeti lista sorrendje megmarad, és egydimenziós listák és tuplik esetén működik.
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]
Listaszerű jelölést használunk.
Itt a következőket használjuk
- Ha az “X és Y” kifejezésben az X hamis az and operátor rövidzárlatos kiértékelésében, akkor az Y nem kerül kiértékelésre (nem hajtódik végre).
- Az append() metódus nem ad vissza semmit.
Ha az eredeti seq lista elemei nem léteznek a látottakban, akkor a és utána értékelődik ki.
A seen.append(x) végrehajtásra kerül, és az elem hozzáadódik a seen-hez.
Mivel az append() metódus None-t ad vissza, a None pedig False, a not seen.append(x) értéke True.
A feltételes kifejezés a listamegértés jelölésében Igaz lesz, és a végső generált lista egyik elemeként hozzáadódik.
Ha az eredeti lista seq elemei jelen vannak a seen-ben, akkor a seen-ben nem szereplő x hamis, és a lista megértésének feltételes kifejezése hamis.
Ezért ezek nem kerülnek hozzáadásra a végső generált lista elemeiként.
Egy másik módszer az argumentum tengelyének beállítása a NumPy np.unique() függvényében, bár az eredmény rendezett lesz.
Duplikált elemek kivonása és új lista létrehozása
Ne őrizze meg az eredeti felsorolás sorrendjét
Ha csak a duplikált elemeket szeretné kivenni az eredeti listából, használja a collections.Counter() funkciót.
Visszaad egy collections.Counter-t (a dictionary egy alosztálya) az elemekkel mint kulcsokkal és az elemek számával mint értékekkel.
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})
Mivel ez a dictionary alosztálya, az items() funkció használható a kulcsok és értékek lekérdezésére. Elegendő olyan kulcsok kinyerése, amelyek száma kettő vagy több.
print([k for k, v in collections.Counter(l).items() if v > 1])
# [3, 2, 1]
Megőrzi az eredeti lista sorrendjét
Ahogy a fenti példában látható, a Python 3.7 óta a collections.Counter kulcsai megtartják az eredeti lista sorrendjét, és így tovább.
A korábbi verziókban elegendő a sorted() funkcióval történő rendezés, valamint a duplikált elemek törlése.
print(sorted([k for k, v in collections.Counter(l).items() if v > 1], key=l.index))
# [3, 2, 1]
Ha a duplikátumokat úgy szeretné kivenni, ahogy vannak, egyszerűen hagyja meg az eredeti lista azon elemeit, amelyek száma kettő vagy annál több. A sorrend is megmarad.
cc = collections.Counter(l)
print([x for x in l if cc[x] > 1])
# [3, 3, 2, 1, 1, 2, 3]
Kétdimenziós tömb (listák listája)
Kétdimenziós tömbök (listák listái) esetén a következő függvények lehetségesek, ha az eredeti lista sorrendje nem marad meg, illetve ha megmarad. Ez egydimenziós listák és tuplik esetében is működik.
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]
Ha duplikátumokkal akarja kivenni, hagyja meg az eredeti listából azokat az elemeket, amelyek száma kettő vagy több.
print([x for x in l_2d if l_2d.count(x) > 1])
# [[1, 1], [0, 1], [0, 1], [1, 1], [1, 1]]
Vegyük észre, hogy mivel a count() számítási bonyolultsága O(n), a fenti függvény, amely ismételten végrehajtja a count()-t, nagyon nem hatékony. Lehet, hogy van egy okosabb megoldás.
A Counter a dictionary alosztálya, így ha olyan listát vagy tuple-t adsz át a collections.Counter() függvénynek, amelynek elemei listák vagy más, nem zárolható objektumok, hiba fog jelentkezni, és nem fogod tudni használni.
# print(collections.Counter(l_2d))
# TypeError: unhashable type: 'list'