Bagaimana cara menghapus kunci dari kamus Python?


Jawaban:


2842

Untuk menghapus kunci terlepas dari apakah itu ada di kamus, gunakan bentuk dua argumen dict.pop():

my_dict.pop('key', None)

Ini akan kembali my_dict[key]jika keyada di kamus, dan Nonesebaliknya. Jika parameter kedua tidak ditentukan (mis. my_dict.pop('key')) Dan keytidak ada, a KeyErrordinaikkan.

Untuk menghapus kunci yang dijamin ada, Anda juga bisa menggunakan

del my_dict['key']

Ini akan menaikkan a KeyErrorjika kunci tidak ada dalam kamus.


153
Terkadang keuntungan menggunakan pop()lebih del: mengembalikan nilai untuk kunci itu. Dengan cara ini Anda bisa mendapatkan dan menghapus entri dari dict dalam satu baris kode.
kratenko

7
Dalam pertanyaan itu tidak diperlukan untuk menjaga nilainya. Ini hanya akan menambah kompleksitas yang tidak dibutuhkan. Jawaban dari @zigg (di bawah) jauh lebih baik.
Salvatore Cosentino

10
@SalvatoreCosentino Saya tidak bisa mengikuti argumen Anda. Bagaimana kode dalam jawaban ini lebih kompleks daripada kode di dalam jawaban lain?
Sven Marnach

33
@SalvatoreCosentino Tidak, mengabaikan nilai pengembalian suatu fungsi sama sekali tidak efisien. Justru sebaliknya - solusi ini jauh lebih cepat daripada try/ exceptsolusi jika kuncinya tidak ada. Anda mungkin menemukan satu atau yang lain lebih mudah dibaca, yang baik-baik saja. Keduanya adalah Python idiomatik, jadi pilihlah apa pun yang Anda inginkan. Tetapi mengklaim bahwa jawaban ini lebih kompleks atau tidak efisien sama sekali tidak masuk akal.
Sven Marnach

5
@ user5359531 Saya tidak mengerti. Bagaimana ini menjadi masalah? Tidak ada satu pun metode pada tipe bawaan Python yang kembali self, jadi akan agak mengejutkan jika yang ini melakukannya.
Sven Marnach

353

Khusus untuk menjawab, "Apakah ada satu cara untuk melakukan ini?"

if 'key' in my_dict: del my_dict['key']

... yah, kamu bertanya ;-)

Namun, Anda harus mempertimbangkan bahwa cara menghapus objek dari a dictini bukan atomik — itu 'key'mungkin terjadi pada my_dictsaat ifpernyataan, tetapi dapat dihapus sebelum deldieksekusi, dalam hal ini delakan gagal dengan a KeyError. Mengingat ini, akan lebih aman untuk menggunakandict.pop atau sesuatu di sepanjang garis

try:
    del my_dict['key']
except KeyError:
    pass

yang, tentu saja, jelas bukan one-liner.


27
Ya, poppasti lebih ringkas, meskipun ada satu keuntungan utama dari melakukannya dengan cara ini: segera jelas apa yang dilakukannya.
zigg

4
The try/exceptpernyataan lebih mahal. Memunculkan pengecualian lambat.
Chris Barker

16
@ ChrisBarker Saya telah menemukan jika kuncinya ada, trysedikit lebih cepat, meskipun jika tidak, trymemang jauh lebih lambat. popcukup konsisten tetapi lebih lambat dari semua tetapi trydengan kunci yang tidak ada. Lihat gist.github.com/zigg/6280653 . Pada akhirnya, itu tergantung pada seberapa sering Anda mengharapkan kunci untuk benar-benar berada di kamus, dan apakah Anda memerlukan atomicity atau tidak, dan, tentu saja, apakah Anda terlibat dalam optimasi prematur;)
zigg

9
Saya percaya nilai kejelasan tidak boleh diabaikan. +1 untuk ini.
Juan Carlos Coto

2
mengenai biaya coba / kecuali, Anda juga bisa pergi if 'key' in mydict: #then del.... Saya perlu mengeluarkan kunci / val dari dict untuk mengurai dengan benar, pop bukan solusi yang sempurna.
Marc

153

Butuh beberapa waktu untuk mencari tahu apa yang sebenarnya my_dict.pop("key", None)dilakukan. Jadi saya akan menambahkan ini sebagai jawaban untuk menghemat waktu Googling orang lain:

pop(key[, default])

Jika kunci ada di kamus, hapus dan kembalikan nilainya, kalau tidak kembalikan standar . Jika default tidak diberikan dan kunci tidak ada dalam kamus, a KeyErrordinaikkan.

Dokumentasi


15
Cukup ketikkan bantuan (dict.pop) pada juru bahasa python.
David Mulder

13
help () dan dir () dapat menjadi teman Anda ketika Anda perlu tahu apa yang dilakukan sesuatu.
David Mulder

3
atau dict.pop?dalam IPython.
Erik Kaplun

51

del my_dict[key]sedikit lebih cepat daripada my_dict.pop(key)untuk menghapus kunci dari kamus ketika kunci ada

>>> import timeit
>>> setup = "d = {i: i for i in range(100000)}"

>>> timeit.timeit("del d[3]", setup=setup, number=1)
1.79e-06
>>> timeit.timeit("d.pop(3)", setup=setup, number=1)
2.09e-06
>>> timeit.timeit("d2 = {key: val for key, val in d.items() if key != 3}", setup=setup, number=1)
0.00786

Tetapi ketika kuncinya tidak ada if key in my_dict: del my_dict[key]sedikit lebih cepat dari my_dict.pop(key, None). Keduanya setidaknya tiga kali lebih cepat daripada deldalam try/ exceptpernyataan:

>>> timeit.timeit("if 'missing key' in d: del d['missing key']", setup=setup)
0.0229
>>> timeit.timeit("d.pop('missing key', None)", setup=setup)
0.0426
>>> try_except = """
... try:
...     del d['missing key']
... except KeyError:
...     pass
... """
>>> timeit.timeit(try_except, setup=setup)
0.133

1
Mengukur timing dari operasi yang cepat seperti itu sangat bodoh. Kode Anda mungkin tidak akan menjadi lebih cepat karena Anda mengubah popa del. Membuat kamus akan sepenuhnya menghapus barang-barang darinya.
Boris

1
@Boris - ini berguna sebagai latihan umum.
Daisy

1
@Daisy apa yang saya katakan adalah bahwa Anda harus memilih sintaks yang paling mudah dibaca bukan operasi yang 300 nanodetik lebih cepat (itulah perbedaan antara deldan popdari set pertama timing di atas)
Boris

Operasi ini juga sangat cepat sehingga timing ini tidak dapat diandalkan.
Boris

46

Jika Anda perlu menghapus banyak kunci dari kamus dalam satu baris kode, saya pikir menggunakan peta () cukup ringkas dan Pythonic dapat dibaca:

myDict = {'a':1,'b':2,'c':3,'d':4}
map(myDict.pop, ['a','c']) # The list of keys to remove
>>> myDict
{'b': 2, 'd': 4}

Dan jika Anda perlu menangkap kesalahan ketika Anda memberi nilai yang tidak ada dalam kamus, gunakan lambda inside map () seperti ini:

map(lambda x: myDict.pop(x,None), ['a', 'c', 'e'])
[1, 3, None] # pop returns
>>> myDict
{'b': 2, 'd': 4}

atau di python3, Anda harus menggunakan pemahaman daftar sebagai gantinya:

[myDict.pop(x, None) for x in ['a', 'c', 'e']]

Berhasil. Dan 'e' tidak menyebabkan kesalahan, meskipun myDict tidak memiliki kunci 'e'.


42
Ini tidak akan berfungsi di Python 3 karena mapdan teman-teman sekarang malas dan mengembalikan iterators. Menggunakan mapefek samping umumnya dianggap praktik buruk; for ... inloop standar akan lebih baik. Lihat Tampilan dan Iterator Daripada Daftar untuk informasi lebih lanjut.
Greg Krimer

5
Terlepas dari selera dan gaya praktik, daftar pemahaman harus tetap bekerja di Py3 [myDict.pop(i, None) for i in ['a', 'c']], karena mereka menawarkan alternatif umum untuk map(dan filter).
Michael Ekoka

@MichaelEkoka Anda tidak harus menggunakan daftar pemahaman untuk efek sampingnya, gunakan for ... inloop reguler .
Boris

@ Boris Anda mungkin benar. Jawaban saya secara khusus berkaitan dengan penggunaan map(), yang sering digunakan untuk efek sampingnya. Alternatif yang direkomendasikan dalam Python adalah daftar pemahaman, yang menurut saya masih cukup mudah dibaca dan secara kognitif ringan sebagai satu-liner (lihat pertanyaan). Hanya digunakan untuk efek sampingnya, kedua konstruksi tersebut memang menghasilkan daftar yang tidak berguna, yang dapat menjadi tidak efisien. Pada Python3, saya tidak mengetahui fungsi bawaan yang dapat dengan aman dan elegan diulang melalui ekspresi generator, tanpa misalnya produk sampingan yang mahal loop(d.pop(k) for k in ['a', 'b']).
Michael Ekoka

Saya terhibur bahwa jawaban saya yang paling banyak dipilih sepanjang waktu mencakup beberapa peretasan yang tidak akan pernah saya gunakan. Pemahaman daftar (opsi 3) adalah pendekatan yang paling buruk, menurut pendapat saya. Gunakan itu.
Marc Maxmeister

20

Anda dapat menggunakan pemahaman kamus untuk membuat kamus baru dengan kunci itu dihapus:

>>> my_dict = {k: v for k, v in my_dict.items() if k != 'key'}

Anda dapat menghapus dengan ketentuan. Tidak ada kesalahan jika keytidak ada.



7

Kami dapat menghapus kunci dari kamus Python dengan beberapa pendekatan berikut.

Menggunakan delkata kunci; itu pendekatan yang hampir sama seperti yang Anda lakukan -

 myDict = {'one': 100, 'two': 200, 'three': 300 }
 print(myDict)  # {'one': 100, 'two': 200, 'three': 300}
 if myDict.get('one') : del myDict['one']
 print(myDict)  # {'two': 200, 'three': 300}

Atau

Kita dapat melakukan hal-hal berikut:

Tetapi orang harus ingat bahwa, dalam proses ini sebenarnya itu tidak akan menghapus kunci apa pun dari kamus daripada membuat kunci spesifik dikecualikan dari kamus itu. Selain itu, saya mengamati bahwa itu mengembalikan kamus yang tidak dipesan sama dengan myDict.

myDict = {'one': 100, 'two': 200, 'three': 300, 'four': 400, 'five': 500}
{key:value for key, value in myDict.items() if key != 'one'}

Jika kita menjalankannya di shell, ia akan menjalankan sesuatu seperti {'five': 500, 'four': 400, 'three': 300, 'two': 200}- perhatikan bahwa itu tidak sama dengan yang dipesan myDict. Sekali lagi jika kita mencoba untuk mencetak myDict, maka kita dapat melihat semua kunci termasuk yang kita kecualikan dari kamus dengan pendekatan ini. Namun, kita dapat membuat kamus baru dengan menetapkan pernyataan berikut ke dalam variabel:

var = {key:value for key, value in myDict.items() if key != 'one'}

Sekarang jika kita mencoba mencetaknya, maka itu akan mengikuti perintah induk:

print(var) # {'two': 200, 'three': 300, 'four': 400, 'five': 500}

Atau

Menggunakan pop()metode.

myDict = {'one': 100, 'two': 200, 'three': 300}
print(myDict)

if myDict.get('one') : myDict.pop('one')
print(myDict)  # {'two': 200, 'three': 300}

Perbedaan antara deldan popapakah itu, menggunakan pop()metode, kita sebenarnya dapat menyimpan nilai kunci jika diperlukan, seperti yang berikut:

myDict = {'one': 100, 'two': 200, 'three': 300}
if myDict.get('one') : var = myDict.pop('one')
print(myDict) # {'two': 200, 'three': 300}
print(var)    # 100

Hancurkan inti ini untuk referensi di masa mendatang, jika menurut Anda ini berguna.


1
Jangan gunakan if myDict.get('one')untuk memeriksa apakah ada kunci! Gagal jika myDict ['one'] memiliki nilai falsey. Juga, dikte tidak memiliki urutan bawaan, jadi tidak masuk akal untuk menyebutkannya.
Rob

Dicts @Rob dipesan dengan urutan penyisipan yang dimulai dengan CPython 3.6 dan semua implementasi Python lainnya dimulai dengan 3.7.
Boris

4

Anda dapat menggunakan penanganan pengecualian jika Anda ingin menjadi sangat verbose:

try: 
    del dict[key]

except KeyError: pass

Namun, ini lebih lambat daripada pop()metode ini, jika kuncinya tidak ada.

my_dict.pop('key', None)

Tidak masalah untuk beberapa tombol, tetapi jika Anda melakukan ini berulang kali, maka metode terakhir adalah taruhan yang lebih baik.

Pendekatan tercepat adalah ini:

if 'key' in dict: 
    del myDict['key']

Tetapi metode ini berbahaya karena jika 'key'dihilangkan di antara dua garis, KeyErrorakan dinaikkan.


1

Saya lebih suka versi abadi

foo = {
    1:1,
    2:2,
    3:3
}
removeKeys = [1,2]
def woKeys(dct, keyIter):
    return {
        k:v
        for k,v in dct.items() if k not in keyIter
    }

>>> print(woKeys(foo, removeKeys))
{3: 3}
>>> print(foo)
{1: 1, 2: 2, 3: 3}

1

Cara lain adalah dengan Menggunakan item () + pemahaman dict

item () ditambah dengan pemahaman dict juga dapat membantu kami mencapai tugas penghapusan pasangan kunci-nilai tetapi, memiliki kelemahan karena tidak menjadi teknik dict tempat. Sebenarnya dict baru jika dibuat kecuali untuk kunci yang tidak ingin kami sertakan.

test_dict = {"sai" : 22, "kiran" : 21, "vinod" : 21, "sangam" : 21} 

# Printing dictionary before removal 
print ("dictionary before performing remove is : " + str(test_dict)) 

# Using items() + dict comprehension to remove a dict. pair 
# removes  vinod
new_dict = {key:val for key, val in test_dict.items() if key != 'vinod'} 

# Printing dictionary after removal 
print ("dictionary after remove is : " + str(new_dict)) 

Keluaran:

dictionary before performing remove is : {'sai': 22, 'kiran': 21, 'vinod': 21, 'sangam': 21}
dictionary after remove is : {'sai': 22, 'kiran': 21, 'sangam': 21}

0

Filter tunggal pada tombol

  • kembalikan "key" dan hapus dari my_dict jika "key" ada di my_dict
  • return None jika "key" tidak ada di my_dict

ini akan berubah my_dictdi tempat (bisa berubah)

my_dict.pop('key', None)

Beberapa filter pada tombol

buat dikte baru (tidak berubah)

dic1 = {
    "x":1,
    "y": 2,
    "z": 3
}

def func1(item):
    return  item[0]!= "x" and item[0] != "y"

print(
    dict(
        filter(
            lambda item: item[0] != "x" and item[0] != "y", 
            dic1.items()
            )
    )
)
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.