Menghapus duplikat dalam daftar

Cukup banyak yang saya butuhkan untuk menulis sebuah program untuk memeriksa jika daftar telah duplikat dan jika itu tidak menghilangkan mereka dan kembali baru daftar dengan item yang tidak't digandakan/dihapus. Ini adalah apa yang saya miliki tapi jujur saya tidak tahu apa yang harus dilakukan.

def remove_duplicates():
    t = ['a', 'b', 'c', 'd']
    t2 = ['a', 'c', 'd']
    for t in t2:
        t.append(t.remove())
    return t
Mengomentari pertanyaan (1)
Larutan

Pendekatan yang umum untuk mendapatkan koleksi unik dari barang-barang adalah dengan menggunakan set. Set unordered koleksi berbeda benda-benda. Untuk membuat satu set dari setiap iterable, anda hanya dapat menyebarkannya ke built-in set() fungsi. Jika anda kemudian perlu daftar lagi, anda dapat pula lulus diatur ke daftar() fungsi.

Contoh berikut harus mencakup apa pun yang anda coba lakukan:

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

Seperti yang anda lihat dari contoh hasil, asli agar tidak dipertahankan. Seperti disebutkan di atas, set sendiri adalah unordered koleksi, sehingga urutan hilang. Ketika mengkonversi satu set kembali ke daftar, urutan sewenang-wenang dibuat.

Menjaga ketertiban

Jika urutan ini penting untuk anda, maka anda akan harus menggunakan mekanisme yang berbeda. Yang sangat umum solusi untuk ini adalah untuk mengandalkan OrderedDict untuk menjaga urutan tombol selama penyisipan:

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

Mulai dengan Python 3.7, built-in kamus dijamin untuk menjaga penyisipan order juga, sehingga anda juga dapat menggunakannya secara langsung jika anda berada di Python 3.7 atau lambat (atau CPython 3.6):

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

Catatan ini telah overhead membuat kamus pertama, dan kemudian membuat daftar dari itu. Jika anda tidak benar-benar perlu untuk menjaga ketertiban, anda lebih baik menggunakan satu set. Check out pertanyaan untuk rincian lebih lanjut dan cara-cara alternatif untuk menjaga agar ketika menghapus duplikat.


Akhirnya diketahui bahwa kedua set serta OrderedDict/dict solusi membutuhkan barang-barang anda untuk menjadi hashable. Hal ini biasanya berarti bahwa mereka harus berubah. Jika anda memiliki untuk berurusan dengan barang-barang yang tidak hashable (misalnya daftar benda-benda), maka anda akan harus menggunakan pendekatan lambat di mana anda pada dasarnya akan memiliki untuk membandingkan setiap item dengan setiap item dalam nested loop.

Komentar (4)

Di Python 2.7, cara baru menghapus duplikat dari iterable sambil menjaga dalam urutan asli adalah:

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

Di Python 3.5, yang OrderedDict memiliki implementasi C. Saya timing menunjukkan bahwa sekarang ini adalah investasi tercepat dan terpendek dari berbagai pendekatan untuk Python 3.5.

Di Python 3.6, biasa dict menjadi terurut dan kompak. (Fitur ini berlaku untuk CPython dan Mount tapi mungkin tidak hadir dalam implementasi lainnya). Yang memberi kita baru cara tercepat deduping sementara tetap mempertahankan urutan:

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

Di Python 3.7, biasa dict dijamin untuk kedua memerintahkan seluruh implementasi. Jadi, terpendek dan tercepat solusinya adalah:

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

It's one-liner: daftar(set(source_list)) akan melakukan trik.

Set adalah sesuatu yang dapat't mungkin memiliki duplikat.

Update: sebuah rangka melestarikan pendekatan dua jalur:

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

Di sini kita menggunakan fakta bahwa OrderedDict mengingat penyisipan urutan tombol, dan tidak berubah ketika nilai di kunci tertentu diperbarui. Kita menyisipkan Benar sebagai nilai-nilai, tetapi kita bisa memasukkan apa-apa, nilai-nilai yang tidak digunakan. (set bekerja banyak seperti dict dengan mengabaikan nilai-nilai, juga.)

Komentar (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]
Komentar (3)

Jika anda don't peduli tentang urutan, lakukan ini:

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

Set dijamin untuk tidak memiliki duplikat.

Komentar (1)

Untuk membuat daftar baru tetap mempertahankan urutan pertama unsur-unsur duplikat di L

newlist=[ii untuk n,ii dalam menghitung(L) jika ii tidak dalam L[:n]]

misalnya jika L=[1, 2, 2, 3, 4, 2, 4, 3, 5] kemudian newlist akan menjadi [1,2,3,4,5]

Ini cek setiap elemen baru telah muncul sebelumnya dalam daftar sebelum menambahkannya. Juga tidak perlu impor.

Komentar (4)

Seorang rekan telah mengirim jawaban yang diterima sebagai bagian dari kode nya kepada saya untuk codereview hari ini. Sementara saya pasti mengagumi keanggunan jawaban dalam pertanyaan, saya tidak senang dengan kinerja. Saya telah mencoba solusi ini (saya menggunakan set untuk mengurangi waktu pencarian)

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

Untuk membandingkan efisiensi, saya menggunakan sampel acak dari 100 bilangan bulat - 62 yang unik

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

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

Berikut ini adalah hasil pengukuran

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

Nah, apa yang terjadi jika diatur dihapus dari solusi?

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

Hasilnya tidak seburuk dengan OrderedDict, tapi masih lebih dari 3 kali dari solusi asli

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

Cara lain melakukan:

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

Ada juga solusi menggunakan Panda dan Numpy. Mereka berdua kembali numpy array sehingga anda harus menggunakan fungsi .kedaftar() jika anda ingin daftar.

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

Panda solusi

Menggunakan Panda fungsi unik():

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

Numpy solusi

Menggunakan numpy fungsi unik().

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

Perhatikan bahwa numpy.unik() juga mengurutkan nilai-nilai. Jadi daftar t2 adalah kembali diurutkan. Jika anda ingin memiliki urutan yang diawetkan menggunakan jawaban ini:

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

Solusi ini tidak begitu elegan dibandingkan dengan yang lain, namun, dibandingkan dengan panda.unik(), numpy.unik() memungkinkan anda juga untuk memeriksa apakah bersarang array yang unik di sepanjang salah satu sumbu dipilih.

Komentar (4)

Sederhana dan mudah:

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

Output:

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

Aku punya dict dalam daftar saya, jadi saya tidak bisa menggunakan pendekatan di atas. Aku punya kesalahan:

TypeError: unhashable type:

Jadi jika anda peduli tentang order dan/atau beberapa item unhashable. Maka anda mungkin menemukan ini berguna:

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

Beberapa mungkin mempertimbangkan daftar pemahaman dengan efek samping untuk tidak menjadi solusi yang baik. Berikut ini's alternatif:

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
Komentar (3)

Semua rangka melestarikan pendekatan I've dilihat di sini sejauh ini baik menggunakan naif perbandingan (dengan O(n^2) waktu-kompleksitas yang terbaik) atau berat-berat OrderedDicts/set+daftar kombinasi yang terbatas untuk hashable input. Berikut ini adalah hash-independen O(nlogn) solusi:

Update ditambahkan kunci argumen, dokumentasi dan Python 3 kompatibilitas.


# from functools import reduce 
Komentar (4)

Jika anda ingin mempertahankan urutan, dan tidak menggunakan modul-modul eksternal berikut ini adalah cara mudah untuk melakukan hal ini:

``python

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

Catatan: metode Ini mempertahankan urutan penampilan, jadi, seperti yang terlihat di atas, sembilan akan datang setelah satu karena ini adalah pertama kali muncul. Namun ini adalah hasil yang sama seperti yang anda akan dapatkan dengan melakukan

python dari koleksi import OrderedDict ulist=daftar(OrderedDict.fromkeys(l))

tapi itu jauh lebih pendek, dan berjalan lebih cepat.

Ini bekerja karena setiap kali fromkeys fungsi mencoba untuk membuat kunci baru, jika nilai yang sudah ada itu hanya akan menimpa. Ini tidak akan mempengaruhi kamus pada semua namun, sebagai fromkeys menciptakan kamus mana semua tombol memiliki value None, sehingga secara efektif menghilangkan semua duplikat dengan cara ini.

Komentar (2)

Cobalah menggunakan set:

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

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

Anda juga bisa melakukan ini:

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

Alasan bahwa karya-karya di atas adalah bahwa index metode pengembalian hanya indeks pertama dari sebuah elemen. Duplikat unsur-unsur yang lebih tinggi memiliki indeks. Lihat di sini:

daftar.indeks(x[, start[, end]]) Return indeks berbasis-nol dalam daftar item pertama yang nilainya adalah x. Menimbulkan ValueError jika tidak ada item tersebut.

Komentar (2)

Mengurangi varian dengan memesan melestarikan:

Asumsikan bahwa kita memiliki daftar:

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

Mengurangi varian (unefficient):

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

5 x lebih cepat tapi lebih canggih

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

Penjelasan:

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]
Komentar (0)

Anda dapat menggunakan fungsi berikut ini:

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

Contoh:

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

Penggunaan:

rem_dupes(my_list)

['ini', 'adalah', 'a', 'daftar', 'dengan', 'dupicates', 'di', 'yang']

Komentar (0)

Pendekatan terbaik untuk menghapus duplikat dari daftar adalah menggunakan set() fungsi, tersedia dalam python, sekali lagi mengubah yang ditetapkan menjadi daftar

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

Ada banyak jawaban yang lain menunjukkan cara yang berbeda untuk melakukan hal ini, tetapi mereka're semua operasi batch, dan beberapa dari mereka membuang urutan asli. Yang mungkin baik-baik saja tergantung pada apa yang anda perlu, tetapi jika anda ingin untuk iterate atas nilai-nilai dalam urutan dari contoh pertama dari masing-masing nilai, dan anda ingin menghapus duplikat on-the-fly terhadap semua sekaligus, anda bisa menggunakan generator ini:

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

Hal ini mengembalikan sebuah generator/iterator, sehingga anda dapat menggunakannya di mana saja bahwa anda dapat menggunakan iterator.

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

print()

Output:

1 2 3 4 5 6 7 8

Jika anda ingin melakukan daftar, anda dapat melakukan ini:

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

print(unique_list)

Output:

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

Tanpa menggunakan 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) 
Komentar (0)