Katakanlah saya punya dua daftar, l1
dan l2
. Saya ingin melakukan l1 - l2
, yang mengembalikan semua elemen l1
tidak masuk l2
.
Saya bisa memikirkan pendekatan loop naif untuk melakukan ini, tetapi itu akan menjadi sangat tidak efisien. Apa cara pythonic dan efisien untuk melakukan ini?
Sebagai contoh, jika sudah l1 = [1,2,6,8] and l2 = [2,3,5,8]
, l1 - l2
harus kembali[1,6]
Jawaban:
Python memiliki fitur bahasa yang disebut Daftar Pemahaman yang sangat cocok untuk membuat hal semacam ini sangat mudah. Pernyataan berikut melakukan apa yang Anda inginkan dan menyimpan hasilnya di
l3
:l3
akan mengandung[1, 6]
.sumber
in
operator tidak seefisien itu dalam daftar.in
pada daftar adalah O (n), sedangkanin
pada himpunan adalah O (1). Namun, hingga Anda mencapai ribuan elemen atau lebih, Anda tidak akan melihat perbedaannya.l3 = [x for x in l1 if x not in set(l2)]
? Saya yakin jikaset(l2)
akan dipanggil lebih dari satu kali.l2s = set(l2)
dan berkatal3 = [x for x in l1 if x not in l2s]
. Sedikit lebih mudah.Salah satu caranya adalah dengan menggunakan set:
sumber
l1
, yang mungkin merupakan efek samping yang tidak diinginkan.timeit.timeit('a = [1,2,3,4]; b = [1,3]; c = [i for i in a if a not in b]', number=100000) -> 0.12061533199999985
timeit.timeit('a = {1,2,3,4}; b = {1,3}; c = a - b', number=100000) -> 0.04106225999998969
. Jadi, jika kinerja merupakan faktor penting, jawaban ini mungkin lebih tepat (dan juga jika Anda tidak peduli dengan duplikat atau pesanan)Sebagai alternatif, Anda juga dapat menggunakan
filter
dengan ekspresi lambda untuk mendapatkan hasil yang diinginkan. Sebagai contoh:Perbandingan Kinerja
Di sini saya membandingkan kinerja semua jawaban yang disebutkan di sini. Seperti yang diharapkan, operasi berbasis Arkku
set
adalah yang tercepat.Perbedaan Set Arkku - Pertama (0,124 usec per loop)
Pemahaman Daftar Daniel Pryden dengan
set
pencarian - Kedua (0,302 usec per loop)Pemahaman Daftar Donat pada daftar biasa - Ketiga (0,552 usec per loop)
Moinuddin Quadri menggunakan
filter
- Keempat (0,972 usec per loop)Akshay Hazari menggunakan kombinasi
reduce
+filter
- Kelima (3,97 usec per loop)PS:
set
tidak mempertahankan urutan dan menghapus elemen duplikat dari daftar. Oleh karena itu, jangan gunakan setel perbedaan jika Anda membutuhkannya.sumber
Memperluas jawaban Donut dan jawaban lainnya di sini, Anda bisa mendapatkan hasil yang lebih baik dengan menggunakan pemahaman generator daripada pemahaman daftar, dan dengan menggunakan
set
struktur data (karenain
operator adalah O (n) pada daftar tetapi O (1) di set).Jadi, inilah fungsi yang akan bekerja untuk Anda:
Hasilnya akan menjadi iterable yang akan malas mengambil daftar yang difilter. Jika Anda memerlukan objek daftar nyata (mis. Jika Anda perlu melakukan
len()
pada hasilnya), maka Anda dapat dengan mudah membuat daftar seperti:sumber
Gunakan tipe himpunan Python. Itu akan menjadi yang paling Pythonic. :)
Juga, karena itu asli, itu harus menjadi metode yang paling optimal juga.
Lihat:
http://docs.python.org/library/stdtypes.html#set
http://docs.python.org/library/sets.htm (untuk python lama)
sumber
l1
menyertakan elemen berulang.gunakan Set Comprehensions {x for x in l2} atau set (l2) untuk mendapatkan set, kemudian gunakan List Comprehensions untuk mendapatkan daftar
kode uji benchmark:
hasil tes benchmark:
sumber
l2set = set( l2 )
bukannyal2set = { x for x in l2 }
Solusi Alternatif:
sumber