Poista ja poimi päällekkäiset elementit luettelosta (array) Pythonissa.

liiketoiminta

Tässä luvussa kuvataan, miten Pythonissa luodaan uusi lista poistamalla tai poimimalla päällekkäisiä elementtejä listasta (array).

Tässä kuvataan seuraavat yksityiskohdat.

  • Poista päällekkäiset elementit ja luo uusia luetteloita.
    • Älä säilytä alkuperäisen luettelon järjestystä:set()
    • Säilyttää alkuperäisen luettelon järjestyksen: dict.fromkeys(),sorted()
    • Kaksiulotteinen joukko (listojen luettelo)
  • Poista päällekkäiset elementit ja luo uusi luettelo.
    • Älä säilytä alkuperäisen luettelon järjestystä
    • Säilyttää alkuperäisen luettelon järjestyksen
    • Kaksiulotteinen joukko (listojen luettelo)

Samaa konseptia voidaan soveltaa tupleihin listojen sijasta.

Katso seuraavasta artikkelista

  • Jos haluat määrittää, onko listalla tai tuplilla päällekkäisiä elementtejä
  • Jos haluat poimia elementtejä, jotka ovat yhteisiä tai epäyhtenäisiä useissa luetteloissa yhden luettelon sijasta.

Huomaa, että luettelot voivat tallentaa erityyppistä dataa ja eroavat selvästi matriiseista. Jos haluat käsitellä matriiseja prosesseissa, jotka vaativat muistin kokoa ja muistiosoitteita tai suurten tietojen numeerista käsittelyä, käytä arraya (standardikirjasto) tai NumPy:tä.

Poista päällekkäiset elementit ja luo uusia luetteloita.

Älä säilytä alkuperäisen luettelon järjestystä: set()

Jos alkuperäisen listan järjestystä ei tarvitse säilyttää, käytä funktiota set(), joka tuottaa set-tyyppisen joukon.

Joukkotyyppi on tietotyyppi, jossa ei ole päällekkäisiä elementtejä. Kun set()-funktiolle annetaan lista tai muu tietotyyppi, päällekkäiset arvot jätetään huomiotta ja palautetaan set-tyyppinen objekti, jonka elementteinä ovat vain yksilölliset arvot.

Jos haluat tehdä siitä tuplen, käytä funktiota 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]

Se voidaan tietysti myös jättää ennalleen. Seuraavassa artikkelissa on lisätietoja set-tyypistä set.

Säilyttää alkuperäisen luettelon järjestyksen: dict.fromkeys(),sorted()

Jos haluat säilyttää alkuperäisen luettelon järjestyksen, käytä sanakirjatyypin luokan metodia fromkeys() tai sisäänrakennettua funktiota sorted().

dict.fromkeys() luo uuden sanakirjaobjektin, jonka avaimet ovat argumenteissa määriteltyjä luetteloita, tupleja jne. Jos toinen argumentti jätetään pois, arvo on None.

Koska sanakirjan avaimissa ei ole päällekkäisiä elementtejä, päällekkäiset arvot jätetään huomiotta, kuten set()-asetuksessa. Lisäksi sanakirjaobjekti voidaan antaa argumenttina list()-operaatiolle, jolloin saadaan lista, jonka elementit ovat sanakirjan avaimia.

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

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

Python 3.7:stä lähtien (CPython on 3.6) on taattu, että dict.fromkeys() säilyttää argumenttien järjestyksen. Aikaisemmat versiot käyttävät sisäänrakennettua funktiota sorted() seuraavasti.

Määritä listatuple-metodi index() argumentin sorted avaimelle, joka palauttaa lajitellun listan elementtejä.

index() on metodi, joka palauttaa arvon indeksin (elementin numeron listassa), joka voidaan määrittää sorted()-metodin avaimeksi, jotta lista voidaan lajitella alkuperäisen listan järjestyksen perusteella. Argumentti key määritetään kutsuttavana (callable) objektina, joten älä kirjoita ().

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

Kaksiulotteinen joukko (listojen luettelo)

Kaksiulotteisille matriiseille (listojen listoille) metodi, jossa käytetään set() tai dict.fromkeys(), aiheuttaa TypeError-virheen.

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'

Tämä johtuu siitä, että ei-hashattavat objektit, kuten listat, eivät voi olla set-tyypin elementtejä tai dict-tyypin avaimia.

Määritä seuraavat funktiot Alkuperäisen listan järjestys säilyy, ja se toimii yksiulotteisille listoille ja tupleille.

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]

Käytetään luettelon ymmärtämisen merkintätapaa.

Tässä käytetään seuraavaa

  • Jos X kohdassa ”X ja Y” on epätosi and-operaattorin oikosulkuarvioinnissa, Y:tä ei arvioida (ei suoriteta).
  • Append()-menetelmä palauttaa Ei mitään.

Jos alkuperäisen listan seq elementtejä ei ole nähtävissä, niin ja jälkeen arvioidaan.
seen.append(x) suoritetaan ja elementti lisätään seen.
Koska append()-metodi palauttaa None ja None on False, not seen.append(x) on True.
Ehdollisesta lausekkeesta tulee listan ymmärtämisen merkintätavalla True, ja se lisätään lopullisen luodun listan elementiksi.

Jos alkuperäisen listan seq alkiot ovat nähtävissä, x ei ole nähtävissä on False, ja listan ymmärtämislausekkeen ehdollinen lauseke on False.
Siksi niitä ei lisätä lopulliseen luetteloon.

Toinen tapa on asettaa argumenttiakseli NumPyn funktiossa np.unique(), vaikka tulos lajitellaan.

Poista päällekkäiset elementit ja luo uusi luettelo.

Älä säilytä alkuperäisen luettelon järjestystä

Jos haluat poimia alkuperäisestä luettelosta vain päällekkäiset elementit, käytä collections.Counter().
Palauttaa collections.Counter -luokan (sanakirjan alaluokka), jossa elementit ovat avaimina ja elementtien lukumäärä arvoina.

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

Koska se on sanakirjan aliluokka, items():n avulla voidaan hakea avaimia ja arvoja. Riittää, että poimitaan avaimet, joiden lukumäärä on vähintään kaksi.

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

Säilyttää alkuperäisen luettelon järjestyksen

Kuten yllä olevassa esimerkissä näkyy, Python 3.7:stä lähtien collections.Counterin avaimet säilyttävät alkuperäisen listan järjestyksen ja niin edelleen.

Aikaisemmissa versioissa lajittelu sorted()-ohjelmalla riittää, samoin kuin päällekkäisten elementtien poistaminen.

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

Jos haluat poistaa kaksoiskappaleet sellaisenaan, jätä alkuperäisestä luettelosta elementit, joiden numero on kaksi tai enemmän. Myös järjestys säilyy.

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

Kaksiulotteinen joukko (listojen luettelo)

Kaksiulotteisille matriiseille (listojen listoille) seuraavat funktiot ovat mahdollisia, kun alkuperäisen listan järjestystä ei säilytetä ja kun se säilytetään. Se toimii myös yksiulotteisille listoille ja tupleille.

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]

Jos haluat poimia kaksoiskappaleet, jätä alkuperäisestä luettelosta elementit, joiden määrä on vähintään kaksi.

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

Huomaa, että koska count():n laskennallinen monimutkaisuus on O(n), edellä esitetty funktio, joka suorittaa count():n toistuvasti, on hyvin tehoton. Voi olla fiksumpi tapa.

Counter on dictionaryn aliluokka, joten jos annat collections.Counter() -oliolle listan tai tuplen, jonka elementit ovat listoja tai muita ei-hakkeroitavia objekteja, tapahtuu virhe, etkä voi käyttää sitä.

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