Je veux faire quelque chose comme:
foo = {'foo':1,'Zip':2,'zam':3,'bar':4}
if ("foo","bar") in foo:
#do stuff
Comment vérifier si "foo" et "bar" sont tous les deux dans dict foo?
Eh bien, vous pouvez faire ceci:
>>> if all (k in foo for k in ("foo","bar")):
... print "They're there!"
...
They're there!
if set(("foo", "bar")) <= set(myDict): ...
Mettez vos propres valeurs pour D et Q
>>> 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
Vous n'avez pas à envelopper le côté gauche dans un ensemble. Vous pouvez simplement faire ceci:
if {'foo', 'bar'} <= set(some_dict):
pass
Cela fonctionne également mieux que la solution all(k in d...)
.
Utiliser sets:
if set(("foo", "bar")).issubset(foo):
#do stuff
Alternativement:
if set(("foo", "bar")) <= set(foo):
#do stuff
Que dis-tu de ça:
if all(key in foo for key in ["foo","bar"]):
# do stuff
pass
Bien que j'aime la réponse d'Alex Martelli, elle ne me semble pas pythonique. C’est-à-dire que j’ai pensé qu’un aspect important d’être Pythonic est d’être facilement compréhensible. Avec cet objectif, <=
N'est pas facile à comprendre.
Bien que ce soit plus de caractères, utiliser issubset()
comme suggéré par la réponse de Karl Voigtland est plus compréhensible. Puisque cette méthode peut utiliser un dictionnaire comme argument, une solution courte et compréhensible est la suivante:
foo = {'foo': 1, 'Zip': 2, 'zam': 3, 'bar': 4}
if set(('foo', 'bar')).issubset(foo):
#do stuff
J'aimerais utiliser {'foo', 'bar'}
À la place de set(('foo', 'bar'))
, parce que c'est plus court. Cependant, ce n'est pas très compréhensible et je pense que les accolades sont trop facilement confondues avec le sens d'un dictionnaire.
La solution d'Alex Martelli set(queries) <= set(my_dict)
est le code le plus court mais peut ne pas être le plus rapide. Supposons que Q = len (requêtes) et D = len (my_dict).
Cela prend O(Q) + O(D) pour faire les deux ensembles, puis (on espère!) Seulement seulement O (min (Q, D )) faire le test de sous-ensemble - en supposant bien sûr que Python est O(1) - c'est le cas le plus défavorable (lorsque la réponse est vraie).
La solution génératrice de hughdbrown (et al?) all(k in my_dict for k in queries)
est le cas le plus défavorable O (Q).
Facteurs compliquant:
(1) Les boucles du gadget basé sur un ensemble sont toutes exécutées à la vitesse du C, alors que le gadget quelconque est en boucle sur bytecode.
(2) L’appelant du gadget quelconque peut être en mesure d’utiliser toute connaissance de probabilité d’échec pour ordonner les éléments de la requête en conséquence, alors que le gadget basé sur un ensemble ne permet pas un tel contrôle.
Comme toujours, si la vitesse est importante, l’étalonnage en conditions opérationnelles est une bonne idée.
Je pense que c'est le plus intelligent et pithonique.
{'key1','key2'} <= my_dict.keys()
Que diriez-vous d'utiliser lambda?
if reduce( (lambda x, y: x and foo.has_key(y) ), [ True, "foo", "bar"] ): # do stuff
Si vous voulez:
ensuite:
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
Cela ne veut pas dire que ce n'est pas quelque chose auquel vous n'avez pas pensé, mais je trouve que la chose la plus simple est généralement la meilleure:
if ("foo" in foo) and ("bar" in foo):
# do stuff
>>> if 'foo' in foo and 'bar' in foo:
... print 'yes'
...
yes
Jason, () n'est pas nécessaire en Python.
Vous pouvez aussi utiliser . Issubset ()
>>> {"key1", "key2"}.issubset({"key1":1, "key2":2, "key3": 3})
True
>>> {"key4", "key2"}.issubset({"key1":1, "key2":2, "key3": 3})
False
>>>
À mon sens, il existe deux méthodes faciles à comprendre parmi toutes les options proposées. Mon critère principal est donc d'avoir un code très lisible, pas un code exceptionnellement rapide. Pour que le code soit compréhensible, je préfère donner les possibilités suivantes:
Le fait que "var <= var2.keys ()" s’exécute plus rapidement dans mes tests ci-dessous, je préfère celui-ci.
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