Ich möchte so etwas tun wie:
foo = {'foo':1,'zip':2,'zam':3,'bar':4}
if ("foo","bar") in foo:
#do stuff
Wie überprüfe ich, ob sowohl 'foo' als auch 'bar' in dict foo sind?
Ich möchte so etwas tun wie:
foo = {'foo':1,'zip':2,'zam':3,'bar':4}
if ("foo","bar") in foo:
#do stuff
Wie überprüfe ich, ob sowohl 'foo' als auch 'bar' in dict foo sind?
Antworten:
Nun, Sie könnten dies tun:
>>> if all (k in foo for k in ("foo","bar")):
... print "They're there!"
...
They're there!
setist er überlegen. Wie immer ... messen Sie es! -)
if {"foo", "bar"} <= myDict.keys(): ...
Wenn Sie noch mit Python 2 arbeiten, können Sie dies tun
if {"foo", "bar"} <= myDict.viewkeys(): ...
Wenn Sie noch auf einem wirklich alten Python <= 2.6 sind, können Sie setdas Diktat aufrufen , aber es wird das gesamte Diktat durchlaufen, um das Set zu erstellen, und das ist langsam:
if set(("foo", "bar")) <= set(myDict): ...
set(("foo","bar")) <= myDict.keys()was das temporäre Set vermeidet und somit viel schneller ist. Für meine Tests ist es ungefähr die gleiche Geschwindigkeit wie für alle, wenn die Abfrage 10 Elemente umfasste. Es wird jedoch langsamer, wenn die Abfrage größer wird.
if {'foo', 'bar'} <= set(myDict): ...
Geben Sie Ihre eigenen Werte für D und Q ein
>>> 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()machen set(q) <= d.viewkeys().
Python 2.7.5hat auch d.keys()Methode.
set(q) <= ...
TypeError: can only compare to a set. Es tut uns leid! :))
d.viewkeys() >= set(q). Ich bin hierher gekommen, um herauszufinden, warum die Bestellung wichtig ist!
Sie müssen die linke Seite nicht in ein Set einwickeln. Sie können dies einfach tun:
if {'foo', 'bar'} <= set(some_dict):
pass
Dies ist auch besser als die all(k in d...)Lösung.
Verwenden von Sets :
if set(("foo", "bar")).issubset(foo):
#do stuff
Alternative:
if set(("foo", "bar")) <= set(foo):
#do stuff
set(d)ist das gleiche wie set(d.keys())(ohne die Zwischenliste, die d.keys()konstruiert)
Wie wäre es damit:
if all([key in foo for key in ["foo","bar"]]):
# do stuff
pass
all.
Ich denke, das ist das klügste und markigste.
{'key1','key2'} <= my_dict.keys()
Obwohl ich Alex Martellis Antwort mag, scheint sie mir nicht pythonisch zu sein. Das heißt, ich dachte, ein wichtiger Teil des Pythonischen ist es, leicht verständlich zu sein. Mit diesem Ziel <=ist nicht leicht zu verstehen.
Während es mehr Zeichen sind, issubset()ist es verständlicher, die von Karl Voigtland vorgeschlagene Antwort zu verwenden. Da diese Methode ein Wörterbuch als Argument verwenden kann, lautet eine kurze, verständliche Lösung:
foo = {'foo': 1, 'zip': 2, 'zam': 3, 'bar': 4}
if set(('foo', 'bar')).issubset(foo):
#do stuff
Ich würde gerne {'foo', 'bar'}anstelle von verwenden set(('foo', 'bar')), weil es kürzer ist. Es ist jedoch nicht so verständlich und ich denke, die Klammern sind zu leicht als Wörterbuch zu verwechseln.
.issubset(). Ich denke, in der Python-Dokumentation zu sein, macht es standardmäßig zu Pythonic.
Die Lösung von Alex Martelli set(queries) <= set(my_dict)ist der kürzeste Code, aber möglicherweise nicht der schnellste. Angenommen, Q = len (Abfragen) und D = len (my_dict).
Dies erfordert O (Q) + O (D), um die beiden Mengen zu erstellen, und dann (man hofft!) Nur O (min (Q, D)), um den Teilmengen-Test durchzuführen - vorausgesetzt natürlich, dass Python-Set-Lookup ist O (1) - dies ist der schlimmste Fall (wenn die Antwort wahr ist).
Die Generatorlösung von hughdbrown (et al?) Ist all(k in my_dict for k in queries)O (Q) im ungünstigsten Fall.
Komplizierende Faktoren:
(1) Die Schleifen im satzbasierten Gadget werden alle mit C-Geschwindigkeit ausgeführt, während das beliebige Gadget den Bytecode durchläuft.
(2) Der Aufrufer des beliebigen Gadgets kann möglicherweise jede Kenntnis der Wahrscheinlichkeit eines Fehlers nutzen, um die Abfrageelemente entsprechend zu ordnen, während das satzbasierte Gadget keine solche Steuerung zulässt.
Wenn Geschwindigkeit wichtig ist, ist wie immer ein Benchmarking unter Betriebsbedingungen eine gute Idee.
Sie können mit .issubset () als auch
>>> {"key1", "key2"}.issubset({"key1":1, "key2":2, "key3": 3})
True
>>> {"key4", "key2"}.issubset({"key1":1, "key2":2, "key3": 3})
False
>>>
Wie wäre es mit Lambda?
if reduce( (lambda x, y: x and foo.has_key(y) ), [ True, "foo", "bar"] ): # do stuff
Falls Sie möchten:
dann:
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
Um nicht zu behaupten, dass dies nicht etwas ist, an das Sie nicht gedacht haben, aber ich finde, dass das Einfachste normalerweise das Beste ist:
if ("foo" in foo) and ("bar" in foo):
# do stuff
>>> if 'foo' in foo and 'bar' in foo:
... print 'yes'
...
yes
Jason, () sind in Python nicht notwendig.
Nur meine Meinung dazu, es gibt zwei Methoden, die für alle gegebenen Optionen leicht zu verstehen sind. Mein Hauptkriterium ist also, gut lesbaren Code zu haben, nicht außergewöhnlich schnellen Code. Um den Code verständlich zu halten, bevorzuge ich gegebene Möglichkeiten:
Die Tatsache, dass "var <= var2.keys ()" in meinen Tests unten schneller ausgeführt wird, bevorzuge ich diesen.
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
Wenn festgestellt wird, ob nur einige Schlüssel übereinstimmen, funktioniert dies:
any_keys_i_seek = ["key1", "key2", "key3"]
if set(my_dict).intersection(any_keys_i_seek):
# code_here
pass
Eine weitere Option, um festzustellen, ob nur einige Schlüssel übereinstimmen:
any_keys_i_seek = ["key1", "key2", "key3"]
if any_keys_i_seek & my_dict.keys():
# code_here
pass
Eine weitere Option, um festzustellen, ob sich alle Schlüssel in einem Diktat befinden:
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
Das scheint zu funktionieren
(), dass das zuerst ausgewertet werden und dazu führen Truewürde, was dann prüfen würde, ob True in ok. Wie funktioniert das eigentlich?!