Saya memiliki daftar dicts, dan saya ingin menghapus dicts dengan pasangan kunci dan nilai yang identik.
Untuk daftar ini: [{'a': 123}, {'b': 123}, {'a': 123}]
Saya ingin mengembalikan ini: [{'a': 123}, {'b': 123}]
Contoh lain:
Untuk daftar ini: [{'a': 123, 'b': 1234}, {'a': 3222, 'b': 1234}, {'a': 123, 'b': 1234}]
Saya ingin mengembalikan ini: [{'a': 123, 'b': 1234}, {'a': 3222, 'b': 1234}]
python
list
dictionary
Brenden
sumber
sumber
set()
Jawaban:
Coba ini:
Strateginya adalah untuk mengubah daftar kamus menjadi daftar tuple di mana tuple berisi item-item dari kamus. Karena tupel dapat di-hash, Anda dapat menghapus duplikat menggunakan
set
(menggunakan pemahaman set di sini, alternatif python yang lebih lama akan menjadiset(tuple(d.items()) for d in l)
) dan, setelah itu, membuat kembali kamus dari tupel dengandict
.dimana:
l
adalah daftar aslid
adalah salah satu kamus dalam daftart
adalah salah satu tupel yang dibuat dari kamusSunting: Jika Anda ingin mempertahankan pemesanan, satu-liner di atas tidak akan berfungsi karena
set
tidak akan melakukan itu. Namun, dengan beberapa baris kode, Anda juga dapat melakukannya:Contoh output:
Catatan: Seperti yang ditunjukkan oleh @alexis, mungkin terjadi dua kamus dengan kunci dan nilai yang sama, tidak menghasilkan tupel yang sama. Itu bisa terjadi jika mereka melalui riwayat kunci tambah / hapus yang berbeda. Jika itu yang menjadi masalah Anda, maka pertimbangkan untuk menyortir
d.items()
sesuai sarannya.sumber
d.items()
tidak dijamin untuk mengembalikan elemen dalam urutan tertentu. Anda harus melakukannyatuple(sorted(d.items()))
untuk memastikan Anda tidak mendapatkan tupel berbeda untuk pasangan nilai kunci yang sama.json
modul seperti yang saya lakukanSatu baris lain berdasarkan daftar pemahaman:
Di sini karena kita dapat menggunakan
dict
perbandingan, kita hanya menyimpan elemen-elemen yang tidak ada dalam daftar awal (gagasan ini hanya dapat diakses melalui indeksn
, karenanya penggunaanenumerate
).sumber
if i not in d[n + 1:]
iterates atas seluruh daftar dicts (darin
tetapi itu hanya membagi dua jumlah total operasi) dan Anda melakukan itu memeriksa setiap elemen dalam kamus Anda sehingga kode ini adalah O (n ^ 2) kompleksitas waktuJawaban lain tidak akan berfungsi jika Anda beroperasi pada kamus bersarang seperti objek JSON deserialized. Untuk kasus ini, Anda dapat menggunakan:
sumber
Jika menggunakan paket pihak ketiga tidak apa-apa maka Anda bisa menggunakan
iteration_utilities.unique_everseen
:Ini menjaga urutan daftar asli dan ut juga dapat menangani barang-barang yang tidak dapat diakses seperti kamus dengan mundur pada algoritma yang lebih lambat (di
O(n*m)
manan
elemen dalam daftar asli danm
elemen unik dalam daftar asli bukanO(n)
). Jika kunci dan nilai hashable, Anda dapat menggunakankey
argumen fungsi tersebut untuk membuat item hashable untuk "uji keunikan" (sehingga berfungsiO(n)
).Dalam kasus kamus (yang membandingkan tanpa urutan) Anda perlu memetakannya ke struktur data lain yang membandingkan seperti itu, misalnya
frozenset
:Perhatikan bahwa Anda tidak boleh menggunakan
tuple
pendekatan sederhana (tanpa pengurutan) karena kamus yang sama tidak harus memiliki urutan yang sama (bahkan dalam Python 3.7 di mana urutan penyisipan - bukan urutan absolut - dijamin):Dan bahkan mengurutkan tuple mungkin tidak berfungsi jika kunci tidak dapat diurutkan:
Tolok ukur
Saya pikir mungkin berguna untuk melihat bagaimana kinerja pendekatan ini dibandingkan, jadi saya melakukan tolok ukur kecil. Grafik benchmark adalah waktu vs. ukuran daftar berdasarkan daftar yang tidak mengandung duplikat (yang dipilih secara sewenang-wenang, runtime tidak berubah secara signifikan jika saya menambahkan beberapa atau banyak duplikat). Ini adalah plot log-log sehingga jangkauan lengkapnya tercakup.
Waktu absolut:
Pengaturan waktu relatif terhadap pendekatan tercepat:
Pendekatan kedua dari mereka adalah yang tercepat di sini. The
unique_everseen
pendekatan dengankey
fungsi di tempat kedua, namun itu pendekatan tercepat yang diawetkan memesan. Pendekatan lain dari jcollado dan theouroureye hampir sama cepatnya. Pendekatan menggunakanunique_everseen
tanpa kunci dan solusi dari Emmanuel dan Scorpil sangat lambat untuk daftar lagi dan berperilaku jauh lebih burukO(n*n)
daripadaO(n)
. Pendekatan stpk denganjson
tidakO(n*n)
tetapi itu jauh lebih lambat daripadaO(n)
pendekatan serupa .Kode untuk mereproduksi tolok ukur:
Untuk kelengkapan di sini adalah waktu untuk daftar yang hanya berisi duplikat:
Pengaturan waktu tidak berubah secara signifikan kecuali
unique_everseen
tanpakey
fungsi, yang dalam hal ini adalah solusi tercepat. Namun itu hanya kasus terbaik (jadi tidak representatif) untuk fungsi itu dengan nilai-nilai yang tidak dapat dicapai karena runtime tergantung pada jumlah nilai unik dalam daftar:O(n*m)
yang dalam hal ini hanya 1 dan karenanya berjalan dalamO(n)
.Penafian: Saya penulis
iteration_utilities
.sumber
Kadang-kadang loop gaya lama masih bermanfaat. Kode ini sedikit lebih panjang dari kode jcollado, tetapi sangat mudah dibaca:
sumber
0
dalamrange(0, len(a))
tidak diperlukan.Jika Anda ingin mempertahankan Order, maka Anda dapat melakukannya
Jika pesanan tidak masalah, maka Anda bisa melakukannya
sumber
dict_values
keluaran yang tidak dapat diserialkan alih-alih daftar. Anda harus memasukkan semuanya dalam daftar lagi.list(frozen.....)
Jika Anda menggunakan Panda dalam alur kerja Anda, satu opsi adalah untuk memberi makan daftar kamus langsung ke
pd.DataFrame
konstruktor. Kemudian gunakandrop_duplicates
danto_dict
metode untuk hasil yang diperlukan.sumber
Bukan jawaban universal , tetapi jika daftar Anda diurutkan berdasarkan beberapa kunci, seperti ini:
maka solusinya sesederhana:
Hasil:
Bekerja dengan kamus bersarang dan (jelas) menjaga ketertiban.
sumber
Anda dapat menggunakan satu set, tetapi Anda harus mengubah dicts menjadi tipe hashable.
Unik sekarang sama
Untuk mendapatkan kembali dikte:
sumber
d.iteritems()
tidak dijamin - jadi Anda mungkin berakhir dengan 'duplikat' diunique
.Berikut ini adalah solusi satu baris cepat dengan pemahaman daftar bersarang ganda (berdasarkan solusi @Emmanuel).
Ini menggunakan kunci tunggal (misalnya,
a
) di setiap dikt sebagai kunci utama, daripada memeriksa apakah seluruh dikt cocokBukan itu yang diminta OP, tapi itu yang membawa saya ke utas ini, jadi saya pikir saya akan memposting solusi yang akhirnya saya dapatkan
sumber
Tidak terlalu pendek tapi mudah dibaca:
Sekarang, daftar
list_of_data_uniq
akan memiliki dikte unik.sumber