Soru Bir sözlükte belirli bir anahtarın var olup olmadığını kontrol edin


Anahtarın değerini güncellemeden önce bir sözlükte bir anahtar olup olmadığını test etmek istedim. Aşağıdaki kodu yazdım:

if 'key1' in dict.keys():
  print "blah"
else:
  print "boo"

Bunun bu görevi yerine getirmenin en iyi yolu olmadığını düşünüyorum. Sözlükte bir anahtar için test etmenin daha iyi bir yolu var mı?


2189
2017-10-21 19:05


Menşei


çağrı dict.keys() belgelere göre bir anahtar listesi oluşturur docs.python.org/2/library/stdtypes.html#dict.keys ama bu modelin, ciddi bir uygulamada, if 'key1' in dict:. - Evgeni Sergeev
Sonunda, neden Python komut dosyalarının çoğunun bu kadar yavaş olduğunu öğrendim :) :(. x in dict.keys() Anahtarları kontrol etmek için Ve bu, Java'daki anahtarlar üzerinde yinelemenin olağan yolu olduğu için oldu. for (Type k : dict.keySet()), bu alışkanlık neden for k in dict.keys() daha doğal hissetmek for k in dict (hangi performans açısından hala iyi olmalı?), ama sonra kontrol tuşları olur if k in dict.keys() da, bu bir sorun ... - Evgeni Sergeev
@EvgeniSergeev if k in dict_: Dict_'ın KEYS'lerinde k varlığı için testler, dolayısıyla hala ihtiyacınız yok dict_.keys(). (Bu beni ısırdı, çünkü bana bir değer Dict. Ama öyle değil. - ToolmakerSteve
@ToolmakerSteve Bu doğru, sadece ihtiyacınız değil, iyi bir uygulama değil. - Evgeni Sergeev
"Dict anahtarını" deneyin - marcelosalloum


Cevaplar:


in bir anahtarın varlığını sınamak için amaçlanan yoldur dict.

d = dict()

for i in xrange(100):
    key = i % 10
    if key in d:
        d[key] += 1
    else:
        d[key] = 1

Bir varsayılan istediyseniz, her zaman kullanabilirsiniz dict.get():

d = dict()

for i in xrange(100):
    key = i % 10
    d[key] = d.get(key, 0) + 1

... ve her zaman kullanmak istediğiniz herhangi bir anahtar için varsayılan bir değer sağlamak istiyorsanız defaultdict itibaren collections modül, böyle:

from collections import defaultdict

d = defaultdict(lambda: 0)

for i in xrange(100):
    d[i % 10] += 1

... ama genel olarak in Anahtar kelime bunu yapmanın en iyi yoludur.


2242
2017-10-21 19:10



Ben sadece kullanıyorum get Eğer öğeyi yine de sözlükten çekeceksem. Kullanımında hiçbir anlamda in  ve öğeyi sözlüğün dışına çekmek. - Jason Baker
Tamamen katılıyorum. Ancak yalnızca bir anahtarın var olup olmadığını bilmeniz gerekiyorsa veya anahtarın tanımlandığı bir durum ile bir varsayılanı kullandığınız bir durum arasında ayrım yapmanız gerekiyorsa, in Bunu yapmanın en iyi yolu. - Chris B.
Referans Bu cevap için python dokümanlar - enkash
anahtar, "False" ile eşdeğer ise 0 Örneğin. Bunu zor yoldan öğrendim: / - Sebastien
'Başarısızlık' sözünün, 'başarısız' sayısının, anahtar başarısızlıklarının sayısının yeterince küçük olması durumunda en hızlı olacağından bahsetmediği için tam bir cevaba katılıyorum. Aşağıdaki bu cevaba bakın: stackoverflow.com/a/1602945/4376643 - Craig Hicks


Anahtarları aramak zorunda değilsiniz:

if 'key1' in dict:
  print "blah"
else:
  print "boo"

Bu çok olacak Daha hızlı sözlükleri, lineer bir arama yapmaktan ziyade, çağıran anahtarların yapacakları karmaşayı kullandığı gibi kullanır.


1099
2017-10-21 19:06



Bu harika. İçinde hala anahtarlar listesinin tersine hareket edeceği izlenimindeydim, fakat bunun bir kümede üyeliği test etmek gibi daha çok çalıştığını görüyorum. - Mohan Gulati
@Mohan Gulati: Bir sözün, değerler ile eşleştirilen anahtarların bir bileşimi olduğunu anlıyorsunuz, değil mi? Bir karma algoritma, anahtarı bir tam sayıya dönüştürür ve tamsayı, eşleşen karma tabloda bir yer bulmak için kullanılır. en.wikipedia.org/wiki/Hash_table - hughdbrown
@Charles Addis, yaklaşık yarım milyon anahtarla çalışan deneyimden, "dict.keys ()" anahtarında "dict key" yazarken en az 10 kat performans artışı elde edersiniz. PEP ve Zen ayrıca, projeniz için kötü olmaları durumunda bunları görmezden gelmeniz gerektiğini belirtir. - ivan_bilan
ivan_bilan - Sadece kendi tezimi çalıştırdım ... Yarım milyon anahtarda, if key in d1 aldı 0.17265701293945312 saniye. çağrı if key in d1.keys() aldı 0.23871088027954102 - Bu bir mikro optimizasyonun klasik tanımıdır. tasarruf 0.07884883880615234 saniye bir performans artışı değildir. - Charles Addis
@Eli Sadece senin için bir test oluşturdum, kendini koşturabilirsin. Sonuçlar sizi şaşırtabilir. ~ 50.000 tuşlu dicts için keys() size .01 ikinci hesaplama yararı sağlar. ~ 500.000 anahtar için keys() size .1 ikinci yarar sağlar. ~ 5.000.000 anahtar için keys() .4 saniye daha hızlı, ancak 50.000.000 anahtar ARAMA keys() 3 SANAYİ HIZLI IS! - Charles Addis


Bir anahtar kelimenin varlığını bir sözlükte kullanarak test edebilirsiniz. içinde anahtar kelime:

d = {'a': 1, 'b': 2}
'a' in d # <== evaluates to True
'c' in d # <== evaluates to False

Bir anahtarın var olup olmadığını denetlemeden önce bir anahtarın varlığını kontrol etmek için ortak bir kullanım, değeri varsayılan olarak ilklendirmesidir (örneğin, değerleriniz listelerse ve örneğin ekleyebileceğiniz boş bir liste olduğundan emin olmak istiyorsanız). Bir anahtar için ilk değeri eklerken). Bu gibi durumlarda, bulabilirsiniz collections.defaultdict() ilginizi çekmek için yazın.

Eski kodda, bazı kullanımları da bulabilirsiniz. has_key(), sözlüklerde anahtarların varlığını kontrol etmek için onaylanmamış bir yöntem (sadece key_name in dict_name, yerine).


226
2017-10-21 19:16



dict.has_key (key) dict anahtar lehine kaldırılmıştır - David Locke
Teknik olarak, has_key olduğu kullanımdan kaldırıldı Python 2.x + için (sadece 3.0+ için değil). Yani, Python 2.x'te yazarken bile, yeni kodun kullanılmaması önerilir. (Gelecekteki sürümlerde uzaklaştığı bilinen bir özellik olduğundan ve bunun yerine kullanmak için mükemmel bir yedek var.) 3.0'da olan şey tamamen kaldırılmış olmasıdır. - ToolmakerSteve
@ToolmakerSteve Elbette doğru ve cevabını yansıtacak şekilde güncelledim. :) - kqr
(Python 2.7 kullanarak), yazdığım bir şeyin çalışma zamanını ağır bir şekilde dikte ederek, 363.235070 ile "dict.keys ()" anahtarını kullanarak paylaştı ve sadece "tuşlar" aramasını kaldırarak 0.260186'ya indi. )" - Ido_f
@Ido_f, benchmark'larınızı lütfen notlandırın. - Charles Addis


Bunu kısaltabilirsiniz:

if 'key1' in dict:
    ...

Ancak, bu en iyi bir kozmetik iyileştirme. Neden bunun en iyi yol olduğuna inanmıyorsunuz?


74
2017-10-21 19:06



Bu çok Kozmetik bir gelişme daha fazla. Bu yöntemi kullanarak bir anahtar bulma zamanı O (1) iken, arama tuşları bir liste oluşturur ve O (n) olur. - Jason Baker
O (1) oldukça doğru görünmüyor. O (log n) gibi bir şey olmadığından emin misin? - spectras
Ortalama bir O (1) ve en kötü O (n) olan tek bir dict arayışının karmaşıklığı. .list () her zaman O (n) olacaktır. wiki.python.org/moin/TimeComplexity - Leo Tindall


Kullanarak tavsiye ederim setdefault bunun yerine yöntem. İstediğin herşeyi yapacağına benziyor.

>>> d = {'foo':'bar'}
>>> q = d.setdefault('foo','baz') #Do not override the existing key
>>> print q #The value takes what was originally in the dictionary
bar
>>> print d
{'foo': 'bar'}
>>> r = d.setdefault('baz',18) #baz was never in the dictionary
>>> print r #Now r has the value supplied above
18
>>> print d #The dictionary's been updated
{'foo': 'bar', 'baz': 18}

40
2017-10-21 19:07



Nedir setdefault OP'nin sorusu ile ilgisi var mı? - hughdbrown
@hughdbrown "Anahtarın değerini güncellemeden önce bir sözlükte bir anahtar olup olmadığını test etmek istedim." Bazı yayınlar, orijinal amaç olmayan bir şeye yanıtlar uyandıran kod içerir. İlk cümlede belirtilen hedefi gerçekleştirmek için, gönderilen örnek kod için bir ikame yedeği olmasa da, setdefault en etkili yöntemdir. - David Berger
Bu üstün bir cevaptır çünkü OP'nin amacını sadece teknik olarak doğru cevabı vermek yerine yerine getirir. Görmek: nedbatchelder.com/blog/201207/... - Niels Bom
Bilgilendirici bir cevap için +1, bana bir şey öğretti. Bununla birlikte, en iyi çözüm, kodlayıcının aklında ne olduğuna bağlıdır; Örneğin. "anahtarın değerini güncellemeden önce" anlamı. Belki de mevcut değilse bir istisna atar (== Yeni anahtar eklemek için izin yok). Belki bir sayım sözlüğü ve mevcut sayıya 1 ekleyecektir, bu durumda, 'd [anahtar] = d.get (anahtar, 0) + 1' en temiz çözümdür (Chris'in gösterdiği gibi, cevabınızdan sonra yazılmıştı). (Gelecek okuyucular buraya geldiğinde, farklı görevler göz önünde bulundurulduğunda, bundan bahsetmekten rahatsız olurum.) - ToolmakerSteve
@NielsBom ... IMHO setdefault bir tek  üstün Mevcut bir giriş gerektiğinde çözüm değil üzerine yazılmalıdır. (Önemli bir durum, fakat bir anahtarın varlığını test etmenin tek nedeni değil.) - ToolmakerSteve


Kabul edilen yanıtın önerilen metotlarının (10m döngüleri) hızlı yürütülmesi hakkında ek bilgi için:

  • 'key' in mydict geçen süre 1.07 sn
  • mydict.get('key') Geçen süre 1.84 sn
  • mydefaultdict['key'] geçen süre 1.07 sn

Bu nedenle kullanarak in veya defaultdict karşı tavsiye edilir get.


35
2018-05-29 11:06



olsun, özünde 1 ve 3 numaralı mermi noktalarının kombinasyonu. - scape
kesinlikle katılıyorum get1.84'leri <1.07 * 2; -P - Paul Rigor


Python'daki sözlük bir get ('key', default) yöntemine sahiptir. Bu nedenle, herhangi bir anahtarın olmaması durumunda varsayılan bir değer ayarlayabilirsiniz.

values = {...}
myValue = values.get('Key', None)

19
2018-03-01 09:03





Kontrol etmek için kullanabilirsiniz has_key() yöntem

if dict.has_key('key1'):
   print "it is there"

Eğer bir değer istiyorsanız o zaman kullanabilirsiniz get() yöntem

a = dict.get('key1', expeced_type)

Bir tuple veya liste veya sözlük veya varsayılan değer olarak herhangi bir dize dönüş değeri olarak kullanmak isterseniz get() yöntem

a = dict.get('key1', {}).get('key2', [])

15
2017-09-10 18:37



.get ve has_key zaten sizden önceki cevaplarda önerildi, has_key de python3'te kaldırıldı. - Padraic Cunningham


Üçlü operatörün kullanılması:

message = "blah" if 'key1' in dict else "booh"
print(message)

14
2017-08-18 22:58