Gibi bir şey yapmak istiyorum:
foo = {'foo':1,'zip':2,'zam':3,'bar':4}
if ("foo","bar") in foo:
#do stuff
Hem 'foo' hem de 'bar' ın dikte foo olup olmadığını nasıl kontrol edebilirim?
Gibi bir şey yapmak istiyorum:
foo = {'foo':1,'zip':2,'zam':3,'bar':4}
if ("foo","bar") in foo:
#do stuff
Hem 'foo' hem de 'bar' ın dikte foo olup olmadığını nasıl kontrol edebilirim?
Yanıtlar:
Bunu yapabilirsin:
>>> if all (k in foo for k in ("foo","bar")):
... print "They're there!"
...
They're there!
set
üstündür. Her zamanki gibi ... ölçün! -)
if {"foo", "bar"} <= myDict.keys(): ...
Hala Python 2'de iseniz, şunları yapabilirsiniz
if {"foo", "bar"} <= myDict.viewkeys(): ...
Hala gerçekten eski bir Python <= 2.6 kullanıyorsanız, set
dikteyi çağırabilirsiniz , ancak seti oluşturmak için tüm dikteyi yineleyecektir ve bu yavaş:
if set(("foo", "bar")) <= set(myDict): ...
set(("foo","bar")) <= myDict.keys()
geçici setten kaçındığını söyleyebilirsiniz , bu yüzden çok daha hızlıdır. Testlerim için, sorgu 10 öğe olduğunda hepsini kullanmakla aynı hızda. Sorgu daha da büyüdükçe yavaşlar.
if {'foo', 'bar'} <= set(myDict): ...
D ve Q için kendi değerlerinizi girin
>>> from timeit import Timer
>>> setup='''from random import randint as R;d=dict((str(R(0,1000000)),R(0,1000000)) for i in range(D));q=dict((str(R(0,1000000)),R(0,1000000)) for i in range(Q));print("looking for %s items in %s"%(len(q),len(d)))'''
>>> Timer('set(q) <= set(d)','D=1000000;Q=100;'+setup).timeit(1)
looking for 100 items in 632499
0.28672504425048828
#This one only works for Python3
>>> Timer('set(q) <= d.keys()','D=1000000;Q=100;'+setup).timeit(1)
looking for 100 items in 632084
2.5987625122070312e-05
>>> Timer('all(k in d for k in q)','D=1000000;Q=100;'+setup).timeit(1)
looking for 100 items in 632219
1.1920928955078125e-05
d.viewkeys()
yapmak zorunda set(q) <= d.viewkeys()
.
Python 2.7.5
vardır d.keys()
da yöntem.
set(q) <= ...
TypeError: can only compare to a set
. Afedersiniz! :))
d.viewkeys() >= set(q)
. Buraya siparişin neden önemli olduğunu bulmaya çalıştım!
Sol tarafı bir sete sarmanıza gerek yok. Bunu sadece yapabilirsiniz:
if {'foo', 'bar'} <= set(some_dict):
pass
Bu aynı zamanda all(k in d...)
çözümden daha iyi performans gösterir .
Kullanılması setleri :
if set(("foo", "bar")).issubset(foo):
#do stuff
Alternatif:
if set(("foo", "bar")) <= set(foo):
#do stuff
set(d)
ile aynıdır set(d.keys())
( d.keys()
inşa eden ara liste olmadan )
Buna ne dersin:
if all([key in foo for key in ["foo","bar"]]):
# do stuff
pass
all
.
Bence bu en akıllı ve pithonic.
{'key1','key2'} <= my_dict.keys()
Alex Martelli'nin cevabını beğenmeme rağmen, bana Pythonic gibi gelmiyor. Yani, Pythonic olmanın önemli bir kısmının kolayca anlaşılabilir olması gerektiğini düşündüm. Bu amaçla, <=
anlaşılması kolay değil.
Daha fazla karakter olsa da, issubset()
Karl Voigtland'ın cevabının önerdiği şekilde kullanmak daha anlaşılır. Bu yöntem sözlüğü bağımsız değişken olarak kullanabildiğinden, kısa ve anlaşılabilir bir çözümdür:
foo = {'foo': 1, 'zip': 2, 'zam': 3, 'bar': 4}
if set(('foo', 'bar')).issubset(foo):
#do stuff
Ben kullanmak istiyorum {'foo', 'bar'}
yerine set(('foo', 'bar'))
daha kısa olduğu için. Ancak, bu anlaşılabilir değil ve braces bir sözlük olmak çok kolay karıştı düşünüyorum.
.issubset()
. Bence Python belgelerinde olmak varsayılan olarak Pythonic yapar.
Alex Martelli'nin çözümü set(queries) <= set(my_dict)
en kısa koddur, ancak en hızlı kod olmayabilir. Q = len (sorgular) ve D = len (my_dict) olduğunu varsayın.
Bu, iki seti yapmak için O (Q) + O (D) ve sonra alt set testi yapmak için sadece O (min (Q, D)) gerektirir - tabii ki Python setinin aramasını varsayarsak O (1) - bu en kötü durumdur (cevap Doğru olduğunda).
Hughdbrown (et al?) 'Nin jeneratör çözeltisi all(k in my_dict for k in queries)
en kötü durum O (Q)' dur .
Karmaşık faktörler:
(1) set tabanlı gadget'taki döngülerin tümü C hızında yapılırken, herhangi bir tabanlı gadget bayt kodu üzerinde döngü yapar.
(2) Herhangi bir tabanlı aracın arayanı, sorgu öğelerini buna göre sıralayamamak için herhangi bir hata olasılığı bilgisini kullanabilirken, set tabanlı araç böyle bir kontrole izin vermez.
Her zaman olduğu gibi, hız önemliyse, operasyonel koşullar altında kıyaslama yapmak iyi bir fikirdir.
Sen kullanabilirsiniz ) (.issubset yanı
>>> {"key1", "key2"}.issubset({"key1":1, "key2":2, "key3": 3})
True
>>> {"key4", "key2"}.issubset({"key1":1, "key2":2, "key3": 3})
False
>>>
Lambda kullanmaya ne dersiniz?
if reduce( (lambda x, y: x and foo.has_key(y) ), [ True, "foo", "bar"] ): # do stuff
İsterseniz:
sonra:
from operator import itemgetter
foo = {'foo':1,'zip':2,'zam':3,'bar':4}
keys = ("foo","bar")
getter = itemgetter(*keys) # returns all values
try:
values = getter(foo)
except KeyError:
# not both keys exist
pass
Bunun aklınıza gelmediği bir şey olmadığını öne sürmek değil, ama en basit şeyin genellikle en iyisi olduğunu görüyorum:
if ("foo" in foo) and ("bar" in foo):
# do stuff
>>> if 'foo' in foo and 'bar' in foo:
... print 'yes'
...
yes
Jason, () Python'da gerekli değildir.
Sadece bunu benim, verilen tüm seçenekleri anlamak kolay iki yöntem vardır. Yani benim ana kriterlerim son derece hızlı değil, çok okunabilir bir koda sahip olmak. Kodu anlaşılır tutmak için verilen olasılıkları tercih ederim:
"Var <= var2.keys ()" aşağıdaki testte daha hızlı yürütüyor olması, bunu tercih ederim.
import timeit
timeit.timeit('var <= var2.keys()', setup='var={"managed_ip", "hostname", "fqdn"}; var2= {"zone": "test-domain1.var23.com", "hostname": "bakje", "api_client_ip": "127.0.0.1", "request_data": "", "request_method": "GET", "request_url": "hvar2p://127.0.0.1:5000/test-domain1.var23.com/bakje", "utc_datetime": "04-Apr-2019 07:01:10", "fqdn": "bakje.test-domain1.var23.com"}; var={"managed_ip", "hostname", "fqdn"}')
0.1745898080000643
timeit.timeit('var.issubset(var2)', setup='var={"managed_ip", "hostname", "fqdn"}; var2= {"zone": "test-domain1.var23.com", "hostname": "bakje", "api_client_ip": "127.0.0.1", "request_data": "", "request_method": "GET", "request_url": "hvar2p://127.0.0.1:5000/test-domain1.var23.com/bakje", "utc_datetime": "04-Apr-2019 07:01:10", "fqdn": "bakje.test-domain1.var23.com"}; var={"managed_ip", "hostname", "fqdn"};')
0.2644960229999924
Yalnızca bazı anahtarların eşleşip eşleşmediğinin belirlenmesi durumunda, bu işe yarar:
any_keys_i_seek = ["key1", "key2", "key3"]
if set(my_dict).intersection(any_keys_i_seek):
# code_here
pass
Sadece bazı tuşların eşleşip eşleşmediğini bulmak için başka bir seçenek:
any_keys_i_seek = ["key1", "key2", "key3"]
if any_keys_i_seek & my_dict.keys():
# code_here
pass
Tüm tuşların bir dikte olup olmadığını tespit etmek için başka bir seçenek:
dict_to_test = { ... } # dict
keys_sought = { "key_sought_1", "key_sought_2", "key_sought_3" } # set
if keys_sought & dict_to_test.keys() == keys_sought:
# yes -- dict_to_test contains all keys in keys_sought
# code_here
pass
>>> ok
{'five': '5', 'two': '2', 'one': '1'}
>>> if ('two' and 'one' and 'five') in ok:
... print "cool"
...
cool
Bu işe yarıyor gibi görünüyor
()
önce değerlendirilecek ve sonuç True
, sonra kontrol eder şüpheli True in ok
. Bu gerçekten nasıl çalışıyor ?!