Python sözlüğünden bir anahtar nasıl kaldırılır?


Yanıtlar:


2839

Bir anahtarı sözlükte olup olmamasına bakılmaksızın silmek için aşağıdaki iki bağımsız değişken formunu kullanın dict.pop():

my_dict.pop('key', None)

Bu dönecektir my_dict[key]eğer keysözlükte var ve Noneaksi. İkinci parametre belirtilmezse (örn. my_dict.pop('key')) Ve keyyoksa, a KeyErroryükseltilir.

Var olduğu garanti edilen bir anahtarı silmek için şunu da kullanabilirsiniz:

del my_dict['key']

KeyErrorAnahtar sözlükte değilse bu bir a değerini yükseltir .


152
Bazen pop()over kullanmanın bir avantajı del: o anahtarın değerini döndürür. Bu şekilde, bir kod satırındaki bir dikmeden bir girdi alabilir ve silebilirsiniz.
kratenko

7
Soruda, değerin korunması gerekli değildir. Bu sadece gereksiz karmaşıklığı artıracaktır. @Zigg'den (aşağıda) cevap çok daha iyi.
Salvatore Cosentino

10
@SalvatoreCosentino Argümanını takip edemem. Bu yanıttaki kod diğer yanıttaki koddan nasıl daha karmaşık?
Sven Marnach

33
@SalvatoreCosentino Hayır, bir işlevin dönüş değerini göz ardı etmek hiç verimsiz değildir. Tam tersi - anahtar yoksa bu çözüm try/ exceptçözümden çok daha hızlıdır . Birini veya diğerini daha kolay okunabilir bulabilirsiniz, bu iyidir. Her ikisi de deyimsel Python, bu yüzden ne istersen seç. Ancak bu cevabın daha karmaşık veya verimsiz olduğunu iddia etmek hiçbir anlam ifade etmiyor.
Sven Marnach

5
@ user5359531 Anlamıyorum. Bu nasıl bir problem? Python'un yerleşik türlerindeki yöntemlerin hiçbiri geri gelmez self, bu yüzden bunu yapsaydı oldukça şaşırtıcı olurdu.
Sven Marnach

353

Özellikle "bunu yapmanın tek bir yolu var mı?"

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

... iyi ;-) sordun

Bir bir nesne silme bu şekilde olsa da, düşünmelisiniz dictolduğunu atomik değil -çok mümkündür 'key'olabilir my_dictsırasında ifaçıklamada, ancak daha önce silinebilir deldurumda olan, yürütülen delbir başarısız olur KeyError. Bu göz önüne alındığında , hatlarında kullanmakdict.pop ya da bir şey kullanmak en güvenli olurdu

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

hangi elbette kesinlikle değil tek liner.


27
Evet, popkesinlikle daha kısa, ancak bu şekilde yapmanın bir avantajı var: ne yaptığını hemen belli ediyor.
zigg

4
try/exceptİfadesi daha pahalıdır. Bir istisna oluşturmak yavaştır.
Chris Barker

16
@ChrisBarker Anahtarın mevcut olup olmadığını fark ettim try, marjinal olarak daha hızlı, eğer yoksa try, gerçekten iyi bir anlaşma daha yavaş. popoldukça tutarlı ancak hepsinden daha yavaş ancak trymevcut olmayan bir anahtarla. Bkz. Gist.github.com/zigg/6280653 . Sonuç olarak, anahtarın sözlükte ne sıklıkta olmasını beklediğinize ve atomisiteye ihtiyacınız olup olmadığına ve elbette erken optimizasyonla
ilgilenip ilgilenmediğinize bağlıdır

9
Açıklığın değerinin göz ardı edilmemesi gerektiğine inanıyorum. Bunun için +1.
Juan Carlos Coto

2
denemek / hariç harcamaları ile ilgili olarak da gidebilirsiniz if 'key' in mydict: #then del.... Doğru ayrıştırmak için bir dikte bir anahtar / val çıkarmak gerekiyordu, pop mükemmel bir çözüm değildi.
Marc

153

Tam olarak ne my_dict.pop("key", None)yaptığını anlamak biraz zaman aldı . Bu yüzden başkalarını kurtarmak için bir cevap olarak ekleyeceğim Google zaman:

pop(key[, default])

Eğer anahtar sözlükte olup, çıkarın ve değerini, başka dönüş dönmek varsayılan . Eğer varsayılan verilmemesi ve anahtar sözlükte değil, bir KeyErroryükseltilir.

belgeleme


15
Python yorumlayıcısına help (dict.pop) yazmanız yeterlidir.
David Mulder

13
Bir şeyin ne yaptığını bilmeniz gerektiğinde help () ve dir () arkadaşlarınız olabilir.
David Mulder

3
veya dict.pop?IPython'da.
Erik Kaplun

51

del my_dict[key]my_dict.pop(key)anahtar mevcut olduğunda bir anahtarı sözlükten kaldırmaktan biraz daha hızlıdır

>>> 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

Ancak anahtar olmadığında if key in my_dict: del my_dict[key], biraz daha hızlıdır my_dict.pop(key, None). Her ikisi de dela try/ exceptifadesinden en az üç kat daha hızlıdır :

>>> 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
Böyle hızlı bir işlemin zamanlamasını ölçmek oldukça aptalca. Kodunuzu büyük olasılıkla çok daha hızlı elde edemeyeceksiniz çünkü a'yı a popolarak değiştirdiniz del. Sözlük oluşturmak, ondan bir şey silmek tamamen cüce olacaktır.
Boris

1
@Boris - Bu genel bir egzersiz olarak yararlıdır.
papatya

1
@daisy Ne dediğimi en okunabilir sözdizimini değil 300 nanosaniye daha hızlı çalışmasını tercih gerektiğidir (kelimenin tam anlamıyla en arasındaki fark delve popyukarıdaki zamanlamaları ilk kümesinden)
Boris

Ayrıca bu işlemler o kadar hızlı ki bu zamanlamalar güvenilir değil.
Boris

46

Bir kod satırında bir sözlükten çok sayıda anahtarı kaldırmanız gerekiyorsa, map () kullanmak oldukça özlü ve Pythonic okunabilir:

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}

Ve sözlükte olmayan bir değeri açtığınız hataları yakalamanız gerekiyorsa, mapda () içindeki lambda'yı şu şekilde kullanın:

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

veya içinde python3, bunun yerine bir liste kavrayışı kullanmalısınız:

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

İşe yarıyor. MyDict 'e' anahtarına sahip olmasa da 'e' hataya neden olmadı.


42
Bu Python 3'te çalışmaz çünkü maparkadaşlar artık tembeldir ve yineleyicilerdir. Kullanılması mapgenellikle yoksul uygulama olarak kabul edilir yan etkiler için; standart bir for ... indöngü daha iyi olurdu. Daha fazla bilgi için bkz. Listeler Yerine Görünümler ve Yineleyiciler .
Greg Krimer

5
Lezzet ve uygulama tarzından bağımsız olarak, liste kavrayışları Py3'te hala çalışmalıdır [myDict.pop(i, None) for i in ['a', 'c']], çünkü bunlar map(ve filter) ' ye genel bir alternatif sunar .
Michael Ekoka

@MichaelEkoka yan etkileri için liste kavrayışları kullanmamalı, düzenli bir for ... indöngü kullanmalısınız .
Boris

@Boris Muhtemelen haklısın. Cevabım, özellikle map()yan etkileri için kullanılan , özellikle kullanmakla ilgilidir . Python tavsiye alternatif olan Bence hala tek astar (soruya bakın) olarak oldukça okunaklı ve bilişsel olarak hafif liste anlama. Her iki yapı da sadece yan etkileri için kullanıldığında, verimsiz olabilen işe yaramaz bir liste ile sonuçlanır. Python3 itibariyle, pahalı bir yan ürün gibi, bir jeneratör ifadesi ile güvenli ve zarif bir şekilde yineleyebilen yerleşik bir fonksiyonun farkında değilim loop(d.pop(k) for k in ['a', 'b']).
Michael Ekoka

Tüm zamanların en çok oylanan cevabımın asla kullanamayacağım bazı hackleri içerdiğini duyuyorum. Bence liste kavraması (seçenek 3) en az kötü yaklaşımdır. Bunu kullan.
Marc Maxmeister

20

Söz konusu anahtar kaldırıldığında yeni bir sözlük oluşturmak için sözlük anlama özelliğini kullanabilirsiniz :

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

Koşullara göre silebilirsiniz. Varsa hata keyyok.



7

Aşağıdaki yaklaşımlarla Python sözlüğünden bir anahtarı silebiliriz.

delAnahtar kelimeyi kullanma ; neredeyse senin gibi aynı yaklaşım -

 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}

Veya

Aşağıdaki gibi yapabiliriz:

Ama kimse bu süreçte aslında olmaz, akılda tutmalı silmek yerine belirli anahtar yapmak yerine sözlükten herhangi bir tuşa dışlanan o sözlükten. Ayrıca, aynı sipariş verilmeyen bir sözlük döndürdüğünü gözlemledim myDict.

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

Kabukta çalıştırırsak, bunun gibi bir şey yürütür {'five': 500, 'four': 400, 'three': 300, 'two': 200}- bununla aynı sırada olmadığına dikkat edin myDict. Yine yazdırmaya çalışırsak myDict, bu yaklaşımla sözlükten hariç tuttuğumuz tüm tuşları görebiliriz. Ancak, aşağıdaki ifadeyi bir değişkene atayarak yeni bir sözlük yapabiliriz:

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

Şimdi yazdırmaya çalışırsak, üst siparişi takip eder:

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

Veya

pop()Yöntemi kullanarak .

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

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

Arasındaki fark delve popbu, kullanıyor pop()yöntemi, aslında saklayabilir anahtarın değerini gerekirse aşağıdaki gibi:

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

Çatal Bu size bu yararlı bulursanız, ileride başvurmak üzere özünü.


1
if myDict.get('one')Bir anahtarın mevcut olup olmadığını kontrol etmek için kullanmayın ! MyDict ['one'] 'da bir falsey değeri varsa başarısız olur. Ayrıca, diktatların doğal bir düzeni yoktur, bu yüzden bundan bahsetmek mantıklı değildir.
Rob

@Rob dikteleri CPython 3.6 ile başlayan ekleme talimatı ve 3.7 ile başlayan diğer tüm Python uygulamaları ile sıralanır.
Boris

4

Çok ayrıntılı olmak istiyorsanız istisna işlemeyi kullanabilirsiniz:

try: 
    del dict[key]

except KeyError: pass

Ancak, pop()anahtar yoksa , yöntemden daha yavaştır .

my_dict.pop('key', None)

Birkaç anahtar için önemli değil, ancak bunu tekrar tekrar yapıyorsanız, ikinci yöntem daha iyi bir bahistir.

En hızlı yaklaşım şudur:

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

Ancak bu yöntem tehlikelidir çünkü 'key'iki çizgi arasında kaldırılırsa, bir KeyErroryükseltilir.


1

Değişmez versiyonu tercih ederim

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

Başka bir yol, items () + dict kavramasını kullanmaktır

dict kavramasıyla birleşmiş öğeler de anahtar / değer çiftini silme görevini gerçekleştirmemize yardımcı olabilir, ancak yerinde bir dict tekniği olmama dezavantajı vardır. Aslında dahil etmek istemediğimiz anahtar dışında yeni bir diksiyon oluşturuldu.

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)) 

Çıktı:

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

0

Anahtarda tek filtre

  • "anahtar" döndür ve my_dict içinde "anahtar" varsa bunu anahtarımdan kaldır
  • my_dict içinde "anahtar" yoksa Hiçbiri döndürme

bu my_dictyerinde değişecek (değişebilir)

my_dict.pop('key', None)

Tuşlarda birden fazla filtre

yeni bir diksiyon oluşturmak (değişmez)

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()
            )
    )
)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.