Bagaimana saya bisa menemukan duplikat dalam daftar Python dan membuat daftar duplikat lain? Daftar hanya berisi bilangan bulat.
python
list
duplicates
MFB
sumber
sumber
Jawaban:
Untuk menghapus duplikat gunakan
set(a)
. Untuk mencetak duplikat, sesuatu seperti:Perhatikan bahwa
Counter
ini tidak terlalu efisien ( timing ) dan mungkin berlebihan di sini.set
akan tampil lebih baik. Kode ini menghitung daftar elemen unik dalam urutan sumber:atau, lebih ringkas:
Saya tidak merekomendasikan gaya yang terakhir, karena tidak jelas apa
not seen.add(x)
yang dilakukan (add()
metode yang ditetapkan selalu kembaliNone
, maka kebutuhan untuknot
).Untuk menghitung daftar elemen yang digandakan tanpa pustaka:
Jika elemen daftar tidak hashable, Anda tidak dapat menggunakan set / dicts dan harus menggunakan solusi waktu kuadratik (bandingkan masing-masing dengan masing-masing). Sebagai contoh:
sumber
O(n)
, karena hanya mengulangi daftar sekali dan mengatur pencarianO(1)
.dup = []
else: dup.append(x)
print()
seen = set()
laludupe = set(x for x in a if x in seen or seen.add(x))
sumber
l
denganset(l)
hanya mengurangi kompleksitas waktu terburuk dan karenanya tidak melakukan apa pun untuk mengatasi masalah efisiensi skala besar dengan jawaban ini. Mungkin itu tidak sesederhana itu. Singkatnya, jangan lakukan ini.Anda tidak perlu menghitung, hanya apakah barang itu dilihat sebelumnya atau tidak. Diadaptasi jawaban itu untuk masalah ini:
Untuk berjaga-jaga soal kecepatan, berikut adalah beberapa timing:
Inilah hasilnya: (dilakukan dengan baik @JohnLaRooy!)
Menariknya, selain timing itu sendiri, peringkat juga sedikit berubah ketika pypy digunakan. Yang paling menarik, pendekatan berbasis-Counter mendapat manfaat besar dari optimasi pypy, sedangkan metode caching yang saya sarankan tampaknya hampir tidak berpengaruh.
Tampaknya efek ini terkait dengan "duplikasi" dari data input. Saya telah menetapkan
l = [random.randrange(1000000) for i in xrange(10000)]
dan mendapatkan hasil ini:sumber
add
setiap kali memasukkan akan diperlukan.pypy
jika Anda memilikinya dan akan mempercepat.Anda bisa menggunakan
iteration_utilities.duplicates
:atau jika Anda hanya menginginkan satu dari setiap duplikat ini dapat digabungkan dengan
iteration_utilities.unique_everseen
:Ia juga dapat menangani elemen yang tidak dapat dihancurkan (namun dengan biaya kinerja):
Itu adalah sesuatu yang hanya bisa dilakukan oleh beberapa pendekatan lain di sini.
Tolak ukur
Saya melakukan patokan cepat yang mengandung sebagian besar (tetapi tidak semua) pendekatan yang disebutkan di sini.
Tolok ukur pertama hanya mencakup sejumlah kecil daftar panjang karena beberapa pendekatan memiliki
O(n**2)
perilaku.Dalam grafik, sumbu y mewakili waktu, sehingga nilai yang lebih rendah berarti lebih baik. Itu juga diplot log-log sehingga berbagai nilai dapat divisualisasikan dengan lebih baik:
Menghapus
O(n**2)
pendekatan saya lakukan tolok ukur lain hingga setengah juta elemen dalam daftar:Seperti yang Anda lihat,
iteration_utilities.duplicates
pendekatannya lebih cepat daripada pendekatan lain mana pun dan bahkan rantaiunique_everseen(duplicates(...))
lebih cepat atau sama cepatnya daripada pendekatan lainnya.Satu hal tambahan yang menarik untuk dicatat di sini adalah bahwa pendekatan panda sangat lambat untuk daftar kecil tetapi dapat dengan mudah bersaing untuk daftar yang lebih panjang.
Namun karena tolok ukur ini menunjukkan sebagian besar pendekatan melakukan kurang lebih sama, sehingga tidak masalah banyak yang digunakan (kecuali untuk 3 yang memiliki
O(n**2)
runtime).Tolok Ukur 1
Tolok Ukur 2
Penolakan
1 ini adalah dari pihak ketiga perpustakaan saya telah menulis:
iteration_utilities
.sumber
Saya menemukan pertanyaan ini sambil mencari sesuatu yang berhubungan - dan bertanya-tanya mengapa tidak ada yang menawarkan solusi berbasis generator? Memecahkan masalah ini adalah:
Saya prihatin dengan skalabilitas, jadi menguji beberapa pendekatan, termasuk item naif yang bekerja dengan baik pada daftar kecil, tetapi skala mengerikan ketika daftar menjadi lebih besar (catatan - akan lebih baik menggunakan timeit, tetapi ini ilustrasi).
Saya menyertakan @ mooooeeeep untuk perbandingan (sangat cepat: tercepat jika daftar input benar-benar acak) dan pendekatan itertools yang bahkan lebih cepat lagi untuk sebagian besar daftar yang diurutkan ... Sekarang termasuk pendekatan panda dari @firelynx - lambat, tetapi tidak begitu mengerikan, dan sederhana. Catatan - pendekatan sort / tee / zip secara konsisten tercepat di mesin saya untuk daftar yang sebagian besar dipesan, moooeeeep tercepat untuk daftar yang diacak, tetapi jarak tempuh Anda mungkin bervariasi.
Keuntungan
Asumsi
Solusi tercepat, entri 1m:
Pendekatan diuji
Hasil untuk tes 'semua dupes' konsisten, menemukan duplikat "pertama" lalu duplikat "semua" dalam array ini:
Ketika daftar dikocok terlebih dahulu, harga semacam itu menjadi jelas - efisiensinya turun secara nyata dan pendekatan @moooeeeep mendominasi, dengan pendekatan set & dict menjadi serupa tetapi berkinerja lebih rendah:
sumber
random.shuffle(c)
memperhitungkannya. Selain itu saya tidak dapat mereplikasi hasil Anda ketika menjalankan skrip yang tidak diubah juga (pemesanan yang sama sekali berbeda), jadi mungkin itu tergantung pada CPU juga.Menggunakan panda:
sumber
collections.Counter baru di python 2.7:
Dalam versi sebelumnya, Anda dapat menggunakan dikt konvensional sebagai gantinya:
sumber
Inilah solusi yang rapi dan ringkas -
sumber
Tanpa mengkonversi ke daftar dan mungkin cara paling sederhana adalah seperti di bawah ini. Ini mungkin berguna selama wawancara ketika mereka meminta untuk tidak menggunakan set
======= lain untuk mendapatkan 2 daftar nilai unik dan nilai duplikat yang terpisah
sumber
Saya akan melakukan ini dengan panda, karena saya sering menggunakan panda
Memberi
Mungkin tidak terlalu efisien, tetapi pasti lebih sedikit kode daripada banyak jawaban lain, jadi saya pikir saya akan berkontribusi
sumber
pda = pd.Series(a)
print list(pda[pda.duplicated()])
contoh ketiga dari jawaban yang diterima memberikan jawaban yang salah dan tidak berusaha memberikan duplikat. Ini versi yang benar:
sumber
Bagaimana kalau hanya loop melalui setiap elemen dalam daftar dengan memeriksa jumlah kejadian, kemudian menambahkannya ke set yang kemudian akan mencetak duplikat. Semoga ini bisa membantu seseorang di luar sana.
sumber
Kita dapat menggunakan
itertools.groupby
untuk menemukan semua item yang memiliki dups:Outputnya adalah:
sumber
dupes = [x for x, y in groupby(sorted(myList)) if len(list(y)) > 1]
Saya kira cara paling efektif untuk menemukan duplikat dalam daftar adalah:
Ini menggunakan
Counter
semua elemen dan semua elemen unik. Mengurangi yang pertama dengan yang kedua hanya akan meninggalkan duplikat.sumber
Agak terlambat, tapi mungkin bermanfaat untuk beberapa. Untuk daftar yang lebih besar, saya menemukan ini bekerja untuk saya.
Menunjukkan keadilan dan semua duplikat serta menjaga ketertiban.
sumber
Cara yang sangat sederhana dan cepat untuk menemukan dupes dengan satu iterasi di Python adalah:
Outputnya adalah sebagai berikut:
Ini dan lebih banyak lagi di blog saya http://www.howtoprogramwithpython.com
sumber
Saya banyak terlambat masuk ke diskusi ini. Meskipun demikian, saya ingin menangani masalah ini dengan satu kalimat. Karena itulah pesona Python. jika kita hanya ingin mendapatkan duplikat ke daftar terpisah (atau koleksi apa pun), saya akan menyarankan untuk melakukan seperti di bawah ini. Katanya kita memiliki daftar duplikat yang dapat kita sebut sebagai 'target'
Sekarang jika kita ingin mendapatkan duplikat, kita dapat menggunakan satu liner seperti di bawah ini:
Kode ini akan menempatkan catatan yang digandakan sebagai kunci dan menghitung sebagai nilai dalam kamus 'duplikat'. Kamus 'duplikat' akan terlihat seperti di bawah ini:
Jika Anda hanya ingin semua catatan dengan duplikat saja dalam daftar, kode yang jauh lebih pendek:
Output akan menjadi:
Ini berfungsi sempurna dalam versi python 2.7.x +
sumber
Python 3.8 one-liner jika Anda tidak ingin menulis algoritma Anda sendiri atau menggunakan pustaka:
Mencetak item dan menghitung:
groupby
mengambil fungsi pengelompokan sehingga Anda dapat menentukan pengelompokan Anda dengan cara yang berbeda dan mengembalikanTuple
bidang tambahan sesuai kebutuhan.groupby
malas jadi seharusnya tidak terlalu lambat.sumber
Beberapa tes lain. Tentu saja ...
... terlalu mahal. Ini sekitar 500 kali lebih cepat (array yang lebih panjang memberikan hasil yang lebih baik) untuk menggunakan metode terakhir berikut:
Hanya 2 loop, tidak ada
l.count()
operasi yang sangat mahal .Berikut ini adalah kode untuk membandingkan metode misalnya. Kode di bawah ini, ini adalah output:
Kode pengujian:
sumber
Metode 1:
Penjelasan: [val untuk idx, val in enumerate (input_list) jika val di input_list [idx + 1:]] adalah pemahaman daftar, yang mengembalikan elemen, jika elemen yang sama hadir dari posisi saat ini, dalam daftar, indeks .
Contoh: input_list = [42,31,42,31,3,31,31,5,6,6,6,6,6,7,42]
dimulai dengan elemen pertama dalam daftar, 42, dengan indeks 0, memeriksa apakah elemen 42, ada di input_list [1:] (yaitu, dari indeks 1 hingga akhir daftar) Karena 42 ada di input_list [1:] , itu akan mengembalikan 42.
Kemudian ia pergi ke elemen 31 berikutnya, dengan indeks 1, dan memeriksa apakah elemen 31 ada di input_list [2:] (yaitu, dari indeks 2 hingga akhir daftar), Karena 31 ada di input_list [2:], itu akan mengembalikan 31.
sama halnya ia menelusuri semua elemen dalam daftar, dan hanya akan mengembalikan elemen berulang / duplikat ke dalam daftar.
Kemudian karena kita memiliki duplikat, dalam daftar, kita perlu memilih satu dari setiap duplikat, yaitu menghapus duplikat di antara duplikat, dan untuk melakukannya, kita memanggil python built-in set bernama (), dan menghapus duplikat,
Kemudian kita dibiarkan dengan satu set, tetapi bukan daftar, dan karenanya untuk mengkonversi dari satu set ke daftar, kita menggunakan, typecasting, list (), dan yang mengubah set elemen ke daftar.
Metode 2:
Penjelasan: Di sini Kami membuat dua daftar kosong, untuk memulai. Lalu teruslah menelusuri semua elemen daftar, untuk melihat apakah ada di temp_list (awalnya kosong). Jika tidak ada di temp_list, maka kami menambahkannya ke temp_list, menggunakan metode append .
Jika sudah ada di temp_list, itu berarti, elemen daftar saat ini adalah duplikat, dan karenanya kita perlu menambahkannya ke dupe_list menggunakan metode append .
sumber
Anda pada dasarnya menghapus duplikat dengan mengonversi ke set (
clean_list
), lalu iterasiraw_list
, sambil menghapus masing-masingitem
dalam daftar bersih untuk terjadinya diraw_list
. Jikaitem
tidak ditemukan,ValueError
Pengecualian yang diangkat ditangkap danitem
ditambahkan keduplicated_items
daftar.Jika indeks item duplikat diperlukan, cukup
enumerate
daftar dan mainkan dengan indeks. (for index, item in enumerate(raw_list):
) yang lebih cepat dan dioptimalkan untuk daftar besar (seperti ribuan + elemen)sumber
penggunaan
list.count()
metode dalam daftar untuk mengetahui elemen duplikat dari daftar yang diberikansumber
satu garis, untuk bersenang-senang, dan di mana diperlukan satu pernyataan.
sumber
sumber
Solusi satu baris:
sumber
Ada banyak jawaban di sini, tapi saya pikir ini relatif sangat mudah dibaca dan mudah dipahami:
Catatan:
sumber
Berikut adalah generator cepat yang menggunakan dict untuk menyimpan setiap elemen sebagai kunci dengan nilai boolean untuk memeriksa apakah item duplikat telah dihasilkan.
Untuk daftar dengan semua elemen yang merupakan tipe hashable:
Untuk daftar yang mungkin berisi daftar:
sumber
sumber
Saat menggunakan toolz :
sumber
inilah cara saya harus melakukannya karena saya menantang diri saya sendiri untuk tidak menggunakan metode lain:
jadi sampel Anda berfungsi sebagai:
sumber
duplist = list(set(a))
.