How do I check that multiple keys are in a dict in a single pass?

Viewed 159435

I want to do something like:

foo = {
    'foo': 1,
    'zip': 2,
    'zam': 3,
    'bar': 4
}

if ("foo", "bar") in foo:
    #do stuff

How do I check whether both foo and bar are in dict foo?

23 Answers

I think this is the smartest and pithonic.

{'key1','key2'} <= my_dict.keys()

check for existence of all keys in a dict:

{'key_1', 'key_2', 'key_3'} <= set(my_dict)

check for existence of one or more keys in a dict:

{'key_1', 'key_2', 'key_3'} & set(my_dict)

You can use .issubset() as well

>>> {"key1", "key2"}.issubset({"key1":1, "key2":2, "key3": 3})
True
>>> {"key4", "key2"}.issubset({"key1":1, "key2":2, "key3": 3})
False
>>>

short and sweet

{"key1", "key2"} <= {*dict_name}

Just my take on this, there are two methods that are easy to understand of all the given options. So my main criteria is have very readable code, not exceptionally fast code. To keep code understandable, i prefer to given possibilities:

  • var <= var2.keys()
  • var.issubset(var2)

The fact that "var <= var2.keys()" executes faster in my testing below, i prefer this one.

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

In the case of determining whether only some keys match, this works:

any_keys_i_seek = ["key1", "key2", "key3"]

if set(my_dict).intersection(any_keys_i_seek):
    # code_here
    pass

Yet another option to find if only some keys match:

any_keys_i_seek = ["key1", "key2", "key3"]

if any_keys_i_seek & my_dict.keys():
    # code_here
    pass

Another option for detecting whether all keys are in a dict:

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: 
    # True -- dict_to_test contains all keys in keys_sought
    # code_here
    pass

Here's an alternative solution in case you want to get the items that didn't match...

not_existing_keys = [item for item in ["foo","bar"] if item not in foo]
if not_existing_keys:
  log.error('These items are missing', not_existing_keys)
my_dict = {
    'name': 'Askavy',
    'country': 'India',
    'age': 30
}

if set(('name', 'country','age')).issubset(my_dict.keys()):
     print("All keys are present in the dictionary") 
else: 
    print("All keys are not present in  the dictionary") 

To me, simple and easy with None key in the middle with pydash ref

import pydash as _
_.get(d, 'key1.key2.key3.whatevermaybeNone.inthemiddle', default=None) )
Related