Apakah ada cara untuk menghapus item dari kamus dengan Python?
Selain itu, bagaimana saya bisa menghapus item dari kamus untuk mengembalikan salinan (yaitu, tidak memodifikasi yang asli)?
python
dictionary
del
richzilla
sumber
sumber
pop
metode perubahan kamus di tempat . Oleh karena itu mengubah referensi ke kamus yang diteruskan dari pemanggil ke "fungsi pembantu". Jadi "fungsi pembantu" tidak perlu mengembalikan apa pun, karena referensi asli ke kamus di pemanggil akan sudah diubah. Jangan berikan pengembalian daridict.pop()
apa pun jika Anda tidak membutuhkannya. EG:do stuff with my_dict; my_dict.pop(my_key, None); do more stuff with my_dict # now doesn't have my_key
. Gunakandeepcopy(my_dict)
jika dibutuhkan.d.pop()
, saya memperbaiki judul untuk mengajukan pertanyaan yang ditentukan dalam detail.d.pop(key)
. Tetapi jika ada yang memodifikasi salinan dangkal, Anda memiliki masalah yang terkenal dengan alias . Ini membantu jika Anda memberi tahu kami konteks yang lebih luas. (Apakah ada hal lain yang memodifikasi nilai dict? Apakah Anda mencoba untuk secara iterate mengulangi daftar? Jika tidak, apa?)Jawaban:
The
del
pernyataan menghilangkan unsur:Namun, ini memutasi kamus yang ada sehingga konten kamus berubah untuk siapa pun yang memiliki referensi ke instance yang sama. Untuk mengembalikan kamus baru , buat salinan kamus:
The
dict()
konstruktor membuat salinan dangkal . Untuk membuat salinan yang dalam, lihatcopy
modul .Perhatikan bahwa membuat salinan untuk setiap dikt
del
/ tugas / dll. berarti Anda beralih dari waktu konstan ke waktu linier, dan juga menggunakan ruang linear. Untuk dikte kecil, ini bukan masalah. Tetapi jika Anda berencana untuk membuat banyak salinan dari dikte besar, Anda mungkin menginginkan struktur data yang berbeda, seperti HAMT (seperti yang dijelaskan dalam jawaban ini ).sumber
dict
saat Anda mengulanginya, itu akan memberi Anda kesalahan:RuntimeError: dictionary changed size during iteration
pop
metode yang sebenarnya melakukan hal yang sama? Bukankah ini lebih pythonic? (menjadi metode dict, bukan kata khusus yang dipesan)?pop
mengubah kamus.Jika Anda ingin menyimpan yang asli, Anda bisa menyalinnya.
sumber
pop
mengembalikan nilai yang 'muncul', yang memungkinkan Anda menggunakan nilai ini untuk alasan apa pun lebih lanjut. Jika tidak lebih "Pythonic", saya akan mengatakan itu tampaknya lebih baik, pasti :). Ini bukan dict, tetapi bekerja dengan cara yang sama untuk keduanya: github.com/ivanlmj/python-prototypes/blob/master/3.4/…pop
dapat diberikan dengan nilai default yang akan dikembalikan ketika kunci hilang dari dict. Ada baiknya ketika Anda perlu menghapus beberapa tombol tetapi beberapa dari mereka mungkin hilang;del
akan menyerahKeyError
dalam kasus seperti itu.Saya pikir solusi Anda adalah cara terbaik untuk melakukannya. Tetapi jika Anda menginginkan solusi lain, Anda dapat membuat kamus baru dengan menggunakan kunci dari kamus lama tanpa menyertakan kunci yang Anda tentukan, seperti ini:
sumber
{i:a[i] for i in a if i not in [0, 1, 2]}
jika Anda ingin menghapus beberapa elemen.{k:v for k,v in a.items() if k != 0}
menurut saya.**kwargs
,some_function(**{k:v for k,v in some_dict.items() if k not 'some_key'})
The del pernyataan adalah apa yang Anda cari. Jika Anda memiliki kamus bernama foo dengan kunci yang disebut 'bar', Anda dapat menghapus 'bar' dari foo seperti ini:
Perhatikan bahwa ini secara permanen memodifikasi kamus yang sedang dioperasikan. Jika Anda ingin menyimpan kamus asli, Anda harus membuat salinan sebelumnya:
The
dict
panggilan membuat salinan dangkal. Jika Anda ingin salinan yang dalam, gunakancopy.deepcopy
.Inilah metode yang dapat Anda salin & tempel, untuk kenyamanan Anda:
sumber
>>>
sering digunakan dalam contoh python? Ya, python-doc mengandung banyak hal seperti itu. Tetapi kode seperti itu tidak nyaman untuk copypaste . Saya bingung ...>>>
meniru notasi mendengarkan dari python dalam mode cli>>>
. Ya, ini gaya REPL, tapi mari kita bicara terus terang: satu-satunya orang yang menulis sampel ini, dan 1000 orang telah membaca ini. Saya pikir, akan sangat bagus untuk menulis contoh dengan cara yang memungkinkan menyalin dan menjalankan dengan mudah. Saya tidak suka menghapus kurung sudut ini dengan tangan. Atau salin baris demi baris .. Jadi saya tidak mengerti: mengapa sudut ini masih ada))) Mungkin saya tidak tahu sesuatu?Ada banyak jawaban yang bagus, tetapi saya ingin menekankan satu hal.
Anda dapat menggunakan
dict.pop()
metode dandel
pernyataan yang lebih umum untuk menghapus item dari kamus. Keduanya mengubah kamus asli, jadi Anda perlu membuat salinan (lihat detail di bawah).Dan keduanya akan menaikkan
KeyError
jika kunci yang Anda berikan kepada mereka tidak ada dalam kamus:dan
Anda harus mengurus ini:
dengan menangkap pengecualian:
dan
dengan melakukan pemeriksaan:
dan
tetapi dengan
pop()
ada juga cara yang jauh lebih ringkas - memberikan nilai pengembalian default:Kecuali Anda menggunakan
pop()
untuk mendapatkan nilai kunci yang dihapus Anda dapat memberikan apa pun, tidak perluNone
. Meskipun mungkin menggunakandel
denganin
memeriksa sedikit lebih cepat karenapop()
menjadi fungsi dengan komplikasinya sendiri yang menyebabkan overhead. Biasanya tidak demikian, sehinggapop()
dengan nilai default cukup baik.Sedangkan untuk pertanyaan utama, Anda harus membuat salinan kamus Anda, untuk menyimpan kamus asli dan memiliki yang baru tanpa kunci dihapus.
Beberapa orang lain di sini menyarankan untuk membuat salinan lengkap (dalam)
copy.deepcopy()
, yang mungkin berlebihan, salinan "normal" (dangkal), menggunakancopy.copy()
ataudict.copy()
, mungkin cukup. Kamus menyimpan referensi ke objek sebagai nilai untuk kunci. Jadi ketika Anda menghapus kunci dari kamus referensi ini dihapus, bukan objek yang direferensikan. Objek itu sendiri dapat dihapus nanti secara otomatis oleh pengumpul sampah, jika tidak ada referensi lain untuk itu di memori. Membuat salinan yang dalam membutuhkan lebih banyak perhitungan dibandingkan dengan salinan yang dangkal, sehingga mengurangi kinerja kode dengan membuat salinan, membuang-buang memori dan memberikan lebih banyak pekerjaan ke GC, kadang-kadang salinan yang dangkal sudah cukup.Namun, jika Anda memiliki objek yang bisa berubah-ubah sebagai nilai kamus dan berencana untuk mengubahnya nanti di kamus yang dikembalikan tanpa kunci, Anda harus membuat salinan yang dalam.
Dengan salinan dangkal:
Dengan salinan dalam:
sumber
A
dict
adalah struktur data yang salah untuk digunakan untuk ini.Tentu, menyalin dict dan muncul dari copy berfungsi, dan begitu pula membangun dict baru dengan pemahaman, tetapi semua penyalinan itu membutuhkan waktu — Anda telah mengganti operasi waktu-konstan dengan operasi waktu-linear. Dan semua salinan itu hidup sekaligus mengambil ruang — ruang linear per salinan.
Struktur data lainnya, seperti upaya hash dipetakan , dirancang untuk kasus penggunaan jenis ini: menambah atau menghapus elemen akan mengembalikan salinan dalam waktu logaritmik, berbagi sebagian besar penyimpanannya dengan yang asli . 1
Tentu ada beberapa kelemahannya. Performanya lebih logaritmik daripada konstan (walaupun dengan basis besar, biasanya 32-128). Dan, sementara Anda dapat membuat API non-mutasi identik dengan
dict
, API "bermutasi" jelas berbeda. Dan, yang paling penting, tidak ada baterai HAMT yang disertakan dengan Python. 2The
pyrsistent
perpustakaan adalah implementasi yang cukup padat berbasis HAMT dict-pengganti (dan berbagai jenis lainnya) untuk Python. Ia bahkan memiliki API evolver yang bagus untuk memindahkan kode mutasi yang ada ke kode persisten semulus mungkin. Tetapi jika Anda ingin secara eksplisit tentang mengembalikan salinan daripada bermutasi, Anda cukup menggunakannya seperti ini:Itulah
d3 = d1.remove('a')
tepatnya pertanyaan yang diajukan.Jika Anda memiliki struktur data yang dapat diubah-ubah seperti
dict
danlist
disematkan di dalamnyapmap
, Anda masih akan memiliki masalah alias — Anda hanya dapat memperbaikinya dengan terus berubah sepanjang jalan, menyematkanpmap
s danpvector
s.1. HAMT juga menjadi populer dalam bahasa seperti Scala, Clojure, Haskell karena mereka bermain sangat baik dengan pemrograman bebas kunci dan memori transaksional perangkat lunak, tetapi tak satu pun dari keduanya sangat relevan dengan Python.
2. Bahkan, ada adalah sebuah HAMT di stdlib, yang digunakan dalam pelaksanaan
contextvars
. PEP yang ditarik sebelumnya menjelaskan alasannya. Tapi ini adalah detail implementasi tersembunyi dari perpustakaan, bukan jenis koleksi publik.sumber
Hasil:
d = {1: 2, '2': 3}
sumber
Cukup panggil del d ['key'].
Namun, dalam produksi, selalu merupakan praktik yang baik untuk memeriksa apakah 'kunci' ada di d.
sumber
try-except
blokir. Setidaknya, ini akan menjadi operasi atom;)d.pop('key', None)
, itu adalah oneliner. Tetapi pertanyaan sebenarnya adalah tentang mendapatkan kamus tanpa satu kunci, dan bukan tentang memodifikasi dict. Jadi pemahaman - adalah pilihan yang baik di sini;)Tidak, tidak ada jalan lain selain itu
Namun, sering membuat salinan dari hanya kamus yang sedikit diubah mungkin bukan ide yang baik karena akan menghasilkan permintaan memori yang relatif besar. Biasanya lebih baik untuk log kamus lama (jika perlu) dan kemudian memodifikasinya.
sumber
sumber
ini tidak melakukan penanganan kesalahan, ia menganggap kuncinya ada dalam dikt, Anda mungkin ingin memeriksa itu terlebih dahulu dan
raise
jika tidaksumber
del test_dict[key]
?Berikut pendekatan desain tingkat atas:
Saya meneruskan kamus dan kunci yang saya inginkan ke dalam fungsi saya, memvalidasi apakah itu kamus dan jika kuncinya baik-baik saja, dan jika keduanya ada, menghapus nilai dari kamus dan mencetak sisa-overs.
Keluaran:
{'B': 55, 'A': 34}
Semoga itu bisa membantu!
sumber
Cuplikan kode di bawah ini akan membantu Anda dengan pasti, saya telah menambahkan komentar di setiap baris yang akan membantu Anda dalam memahami kode.
atau Anda juga dapat menggunakan dict.pop ()
atau pendekatan yang lebih baik
sumber
Berikut variasi lain menggunakan pemahaman daftar:
Pendekatan ini didasarkan pada jawaban dari pos ini: Cara yang efisien untuk menghapus kunci dengan string kosong dari dict
sumber
if v
untukif k is not 'a'
menjawab op. Tapi saya tidak berpikir itu cara yang efisien, ini menghilangkan elemen dalam O (n) daripada O (log n) seperti yang dilakukan pop atau del.Kode berikut akan membuat salinan dict
species
dan menghapus item yang tidak adatrans_HI
sumber