Eliminarea duplicate în liste

Destul de mult am nevoie pentru a scrie un program pentru a verifica daca o lista are orice duplicate și dacă nu se elimină-le și întoarce o nouă listă cu elementele care au fost't duplicat/eliminat. Aceasta este ceea ce am, dar sincer să fiu nu știu ce să fac.

def remove_duplicates():
    t = ['a', 'b', 'c', 'd']
    t2 = ['a', 'c', 'd']
    for t in t2:
        t.append(t.remove())
    return t
Comentarii la întrebare (1)
Soluția

Abordarea comună pentru a obține o colecție unică de elemente este de a utiliza un set. Seturi sunt neordonate colecții de distincte obiecte. Pentru a crea un set de la orice iterable, puteți trece pur și simplu la built-in [set()](http://docs.python.org/3/library/functions.html#func-set funcția). Dacă mai târziu nevoie de o lista din nou, în mod similar, puteți trece setat la [lista()](http://docs.python.org/3/library/functions.html#func-list funcția).

Următorul exemplu ar trebui să acopere orice ai încerca să faci:

>>> 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]

După cum puteți vedea din exemplul urmare, ordinea inițială nu este menținută. După cum sa menționat mai sus, seturi înșiși sunt colecții neordonate, deci ordinea este pierdut. Când se face conversia de la un set înapoi la o listă, o ordine arbitrară este creat.

Pentru menținerea ordinii

Dacă scopul este de important pentru tine, atunci va trebui să utilizați un mecanism diferit. O soluție comună pentru acest lucru este să se bazeze pe OrderedDict să păstreze ordinea de chei timpul de inserție:

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

Începând cu Python 3.7, built-in dicționar este garantat pentru a menține inserție pentru ca de bine, astfel încât să puteți utiliza, de asemenea, că în mod direct, dacă sunteți pe Python 3.7 sau mai târziu (sau CPython 3.6):

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

Rețineți că acest lucru are aeriene de a crea un dicționar în primul rând, și apoi a crea o listă de la ea. Dacă nu aveți de fapt nevoie pentru a păstra ordinea, esti mai bine folosind un set. Check out această întrebare pentru mai multe detalii și modalități alternative de a păstra ordinea, atunci când eliminarea duplicatelor.


În cele din urmă act de faptul că atât "set", precum și OrderedDict/dict soluții nevoie de un produs pentru a fi hashable. De obicei, aceasta înseamnă că ei trebuie să fie imuabile. Dacă ai de-a face cu elemente care nu sunt hashable (de exemplu, lista de obiecte), atunci va trebui să utilizați o abordare lent în care va în principiu, trebuie să compară fiecare element cu fiecare alt element într-o buclă imbricată.

Comentarii (4)

În Python 2.7, noul mod de a scoate duplicate dintr-un iterable în timp ce menținându-l în ordinea inițială este:

>>> from collections import OrderedDict
>>> list(OrderedDict.fromkeys('abracadabra'))
['a', 'b', 'r', 'c', 'd']

În Python 3.5, la OrderedDict are o implementare C. Timpii mei arată că acest lucru este cel mai rapid și cel mai scurt de diverse abordări pentru Python 3.5.

În Python 3.6, regulat dict a devenit atât de ordonat si compact. (Această caracteristică este valabil pentru CPython și PyPy dar nu poate prezenta în alte implementări). Asta ne dă un nou cel mai rapid mod de deduping păstrând în același timp pentru:

>>> list(dict.fromkeys('abracadabra'))
['a', 'b', 'r', 'c', 'd']

În Python 3.7, regulat dict este garantat pentru a comandat peste toate implementările. Deci, cea mai scurtă și mai rapidă soluție este:

>>> list(dict.fromkeys('abracadabra'))
['a', 'b', 'r', 'c', 'd']
Comentarii (6)

L's o o-liner: lista(set(source_list))` va face truc.

Un " set " este ceva care poate't, eventual, au duplicate.

Update: un ordin de conservare abordare este de două linii:

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

Aici vom folosi faptul că OrderedDict își amintește de inserție scopul de chei, și să nu-l schimbe atunci când o valoare la o anumită cheie este actualizat. Vom introduce "Adevărat" ca valori, dar putem introduce nimic, valorile nu sunt utilizate. ("set" funcționează ca un dict cu ignorate de valori, de asemenea.)

Comentarii (3)
>>> t = [1, 2, 3, 1, 2, 5, 6, 7, 8]
>>> t
[1, 2, 3, 1, 2, 5, 6, 7, 8]
>>> s = []
>>> for i in t:
       if i not in s:
          s.append(i)
>>> s
[1, 2, 3, 5, 6, 7, 8]
Comentarii (3)

Dacă tu nu't grijă despre scopul, doar face acest lucru:

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

Un " set " este garantat de a nu fi duplicate.

Comentarii (1)

Pentru a face o nouă listă de fixare ordinea de primele elemente de duplicate în L

newlist=[ii pentru n,ii enumera(L) dacă a ii-a nu L[:n]]

de exemplu, dacă Am=[1, 2, 2, 3, 4, 2, 4, 3, 5]`` apoi ``newlist va fi [1,2,3,4,5]

Acest pas se verifică fiecare element nou nu a apărut anterior în lista înainte de a o adăuga. De asemenea, nu are nevoie de importuri.

Comentarii (4)

Un coleg a trimis răspunsul acceptat ca parte din codul lui la mine pentru un codereview astăzi. În timp ce eu admir eleganta de a răspunde la întrebare, eu nu sunt fericit cu performanța. Am încercat această soluție (eu folosesc set pentru a reduce căutare de timp)

def ordered_set(in_list):
    out_list = []
    added = set()
    for val in in_list:
        if not val in added:
            out_list.append(val)
            added.add(val)
    return out_list

Pentru a compara eficiența, am folosit un eșantion aleatoriu de 100 de numere întregi - 62 au fost unice

from random import randint
x = [randint(0,100) for _ in xrange(100)]

In [131]: len(set(x))
Out[131]: 62

Aici sunt rezultatele măsurătorilor

In [129]: %timeit list(OrderedDict.fromkeys(x))
10000 loops, best of 3: 86.4 us per loop

In [130]: %timeit ordered_set(x)
100000 loops, best of 3: 15.1 us per loop

Ei bine, ce se întâmplă dacă setul este îndepărtat din soluție?

def ordered_set(inlist):
    out_list = []
    for val in inlist:
        if not val in out_list:
            out_list.append(val)
    return out_list

Rezultatul nu este la fel de rău ca și cu OrderedDict, dar încă mai mult de 3 ori de soluția inițială

In [136]: %timeit ordered_set(x)
10000 loops, best of 3: 52.6 us per loop
Comentarii (2)

Un alt mod de a face:

>>> seq = [1,2,3,'a', 'a', 1,2]
>> dict.fromkeys(seq).keys()
['a', 1, 2, 3]
Comentarii (1)

Există, de asemenea, soluții folosind Panda și Numpy. Amândoi se întoarcă numpy matrice deci va trebui să utilizați funcția .tolist() dacă doriți o listă.

t=['a','a','b','b','b','c','c','c']
t2= ['c','c','b','b','b','a','a','a']

Panda soluție

Folosind Panda funcția unic():

import pandas as pd
pd.unique(t).tolist()
>>>['a','b','c']
pd.unique(t2).tolist()
>>>['c','b','a']

Numpy soluție

Folosind numpy funcția unic().

import numpy as np
np.unique(t).tolist()
>>>['a','b','c']
np.unique(t2).tolist()
>>>['a','b','c']

Rețineți că numpy.unic (), de asemenea, un fel de valori. Deci lista " t2 " este returnat-a rezolvat. Dacă doriți să aveți pentru conservate utilizare ca în acest răspuns:

_, idx = np.unique(t2, return_index=True)
t2[np.sort(idx)].tolist()
>>>['c','b','a']

Soluția nu este atât de elegant în comparație cu alții, cu toate acestea, în comparație cu panda.unic(), numpy.unic() vă permite, de asemenea, pentru a verifica dacă tablouri imbricate sunt unice de-a lungul o anumită axă.

Comentarii (4)

Simplu și ușor:

myList = [1, 2, 3, 1, 2, 5, 6, 7, 8]
cleanlist = []
[cleanlist.append(x) for x in myList if x not in cleanlist]

Ieșire:

>>> cleanlist 
[1, 2, 3, 5, 6, 7, 8]
Comentarii (2)

Am avut un dict în lista mea, așa că nu am putut folosi metoda de mai sus. Am eroarea:

TypeError: unhashable type:

Deci, dacă îți pasă pentru și/sau unele elemente sunt unhashable. Atunci s-ar putea găsi acest util:

def make_unique(original_list):
    unique_list = []
    [unique_list.append(obj) for obj in original_list if obj not in unique_list]
    return unique_list

Unii ar putea lua în considerare lista de înțelegere cu un efect secundar de a nu fi o soluție bună. Aici's o alternativă:

def make_unique(original_list):
    unique_list = []
    map(lambda x: unique_list.append(x) if (x not in unique_list) else False, original_list)
    return unique_list
Comentarii (3)

Tot pentru menținerea abordărilor I'am văzut aici, atât de departe folosi fie naiv comparație (cu O(n^2) timp-complexitatea în cel mai bun) sau cu greutate grele OrderedDicts/ " set " + "listă" de combinații, care sunt limitate la hashable intrări. Aici este un hash-independent de O(nlogn) soluție:

Update adăugat "cheia" de argument, documentare și Python 3 compatibilitate.


# from functools import reduce 
Comentarii (4)

Dacă doriți să păstreze ordinea, și nu folosi orice module externe aici este o modalitate ușoară de a face acest lucru:

``python

t = [1, 9, 2, 3, 4, 5, 3, 6, 7, 5, 8, 9] listă(dict.fromkeys(t)) [1, 9, 2, 3, 4, 5, 6, 7, 8] ``

Notă: Această metodă păstrează ordinea de apariție, așa cum am văzut mai sus, nouă va veni după o pentru că a fost prima dată când a apărut. Acest lucru însă, este același rezultat ca te-ar primi cu

python din colecțiile de import OrderedDict ulist=lista(OrderedDict.fromkeys(l))

dar este mult mai scurt, și rulează mai rapid.

Acest lucru funcționează pentru că de fiecare dată când fromkeys funcția încearcă să creeze o nouă cheie, dacă valoarea deja există pur și simplu se va suprascrie. Acest lucru va afecta dicționar deloc cu toate acestea, cafromkeys` creează un dicționar în care toate cheile au valoarea "Nici unul", în mod eficient, astfel se elimina toate duplicatele acest fel.

Comentarii (2)

Încercați să utilizați seturi:

import sets
t = sets.Set(['a', 'b', 'c', 'd'])
t1 = sets.Set(['a', 'b', 'c'])

print t | t1
print t - t1
Comentarii (0)

Ai putea, de asemenea, face acest lucru:

>>> t = [1, 2, 3, 3, 2, 4, 5, 6]
>>> s = [x for i, x in enumerate(t) if i == t.index(x)]
>>> s
[1, 2, 3, 4, 5, 6]

Motivul pentru care funcționează de mai sus este că "index" metoda returnează doar primul indice al unui element. Elemente duplicat fi mai mari indici. Consultați aici:

listă.index(x[, start[, end]]) Return index bazat pe zero în lista de primul element a cărui valoare este x. Ridică o ValueError dacă nu există nici un astfel de element.

Comentarii (2)

Reducerea varianta cu comanda conserva:

Să presupunem că avem lista:

l = [5, 6, 6, 1, 1, 2, 2, 3, 4]

Reduce variant (unefficient):

>>> reduce(lambda r, v: v in r and r or r + [v], l, [])
[5, 6, 1, 2, 3, 4]

5 x mai rapid, dar mult mai sofisticat

>>> reduce(lambda r, v: v in r[1] and r or (r[0].append(v) or r[1].add(v)) or r, l, ([], set()))[0]
[5, 6, 1, 2, 3, 4]

Explicație:

default = (list(), set())
# user list to keep order
# use set to make lookup faster

def reducer(result, item):
    if item not in result[1]:
        result[0].append(item)
        result[1].add(item)
    return result

reduce(reducer, l, default)[0]
Comentarii (0)

Puteți utiliza următoarele funcții:

def rem_dupes(dup_list): 
    yooneeks = [] 
    for elem in dup_list: 
        if elem not in yooneeks: 
            yooneeks.append(elem) 
    return yooneeks

Exemplu:

my_list = ['this','is','a','list','with','dupicates','in', 'the', 'list']

Utilizare:

rem_dupes(my_list)

['asta', 'este', 'un', 'list', 'cu', 'dupicates', 'in', 'la']

Comentarii (0)

Cea mai bună abordare de eliminarea duplicate dintr-o listă se utilizează set() funcție disponibilă în python, din nou, convertirea setați în listă

In [2]: some_list = ['a','a','v','v','v','c','c','d']
In [3]: list(set(some_list))
Out[3]: ['a', 'c', 'd', 'v']
Comentarii (1)

Există multe alte răspunsuri sugerează diferite moduri de a face acest lucru, dar ei're toate operațiunile de lot, iar unele dintre ele arunca ordinea inițială. Care ar putea fi bine în funcție de ceea ce aveți nevoie, dar dacă vrei să itera peste valorile în ordinea de primă instanță din fiecare valoare, și doriți pentru a elimina duplicatele de pe-the-fly față de toate la o dată, ai putea folosi acest generator:

def uniqify(iterable):
    seen = set()
    for item in iterable:
        if item not in seen:
            seen.add(item)
            yield item

Acesta returnează un generator/iterator, astfel încât să puteți folosi oriunde pe care le puteți folosi un iterator.

for unique_item in uniqify([1, 2, 3, 4, 3, 2, 4, 5, 6, 7, 6, 8, 8]):
    print(unique_item, end=' ')

print()

Ieșire:

1 2 3 4 5 6 7 8

Daca vrei o "listă", puteți face acest lucru:

unique_list = list(uniqify([1, 2, 3, 4, 3, 2, 4, 5, 6, 7, 6, 8, 8]))

print(unique_list)

Ieșire:

[1, 2, 3, 4, 5, 6, 7, 8]
Comentarii (2)

Fără a utiliza set

data=[1, 2, 3, 1, 2, 5, 6, 7, 8]
uni_data=[]
for dat in data:
    if dat not in uni_data:
        uni_data.append(dat)

print(uni_data) 
Comentarii (0)