Odstranjevanje podvajanj na seznamih

V glavnem moram napisati program, ki preveri, ali ima seznam podvojene elemente, in če jih odstrani ter vrne nov seznam z elementi, ki niso bili podvojeni/odstranjeni. To je tisto, kar imam, vendar če sem iskren, ne vem, kaj naj naredim.

def remove_duplicates():
    t = ['a', 'b', 'c', 'd']
    t2 = ['a', 'c', 'd']
    for t in t2:
        t.append(t.remove())
    return t
Rešitev

Običajen pristop za pridobitev edinstvene zbirke elementov je uporaba set. Zbirke so neurejene zbirke različnih predmetov. Če želite ustvariti množico iz katere koli iterable, jo lahko preprosto posredujete vgrajeni funkciji set(). Če pozneje spet potrebujete pravi seznam, lahko množico podobno posredujete funkciji list().

Naslednji primer bi moral zajeti vse, kar želite narediti:

>>> t = [1, 2, 3, 1, 2, 5, 6, 7, 8]
>>> t
[1, 2, 3, 1, 2, 5, 6, 7, 8]
>>> list(set(t))
[1, 2, 3, 5, 6, 7, 8]
>>> s = [1, 2, 3]
>>> list(set(t) - set(s))
[8, 5, 6, 7]

Kot je razvidno iz rezultata primera, prejšnji vrstni red ni ohranjen. Kot je bilo omenjeno zgoraj, so zbirke same po sebi neurejene zbirke, zato se vrstni red izgubi. Pri pretvorbi množice nazaj v seznam se ustvari poljuben vrstni red.

Ohranjanje vrstnega reda

Če vam je vrstni red pomemben, boste morali uporabiti drug mehanizem. Zelo pogosta rešitev za to je, da se zanašamo na OrderedDict za ohranjanje vrstnega reda ključev med vstavljanjem:

>>> from collections import OrderedDict
>>> list(OrderedDict.fromkeys(t))
[1, 2, 3, 5, 6, 7, 8]

Od različice Python 3.7 je zagotovljeno, da vgrajeni slovar prav tako ohranja vrstni red vstavljanja, zato ga lahko uporabite tudi neposredno, če uporabljate Python 3.7 ali novejši (ali CPython 3.6):

>>> list(dict.fromkeys(t))
[1, 2, 3, 5, 6, 7, 8]

Upoštevajte, da je pri tem treba najprej ustvariti slovar in nato iz njega ustvariti seznam. Če vam ni treba ohraniti vrstnega reda, je bolje uporabiti množico. Za več podrobnosti in alternativne načine ohranjanja vrstnega reda pri odstranjevanju dvojnikov si oglejte to vprašanje.


Nazadnje upoštevajte, da tako rešitev set kot tudi rešitev OrderedDict/dict zahtevata, da so vaši elementi hashabilni. To običajno pomeni, da morajo biti nespremenljivi. Če se morate ukvarjati s predmeti, ki niso hashabilni (npr. objekti s seznamom), boste morali uporabiti počasen pristop, pri katerem boste morali vsak predmet primerjati z vsakim drugim predmetom v vgnezdeni zanki.

Komentarji (4)

Gre za en stavek: list(set(source_list)) bo opravil trik.

Set je nekaj, kar se ne more podvajati.

Posodobitev: pristop, ki ohranja vrstni red, je sestavljen iz dveh vrstic:

from collections import OrderedDict
OrderedDict((x, True) for x in source_list).keys()

Tu uporabimo dejstvo, da si OrderedDict zapomni vrstni red vstavljanja ključev in ga ne spremeni, ko se vrednost na določenem ključu posodobi. Kot vrednosti vstavimo True, vendar bi lahko vstavili karkoli, vrednosti se le ne uporabljajo. (Tudi set deluje podobno kot dict z ignoriranimi vrednostmi.)

Komentarji (3)

Če vam je za vrstni red vseeno, naredite to:

def remove_duplicates(l):
    return list(set(l))

Zagotovljeno je, da se set ne bo podvajal.

Komentarji (1)