Checking for multiplexed keys in a dict

I have a dict () like,

xyz = {"a":{"b":[1,2,3]}}

      

I want to check if a nested dict has key "b" or "c". I can check one key, for example

>>> "b" in xyz.get("a",{})
True

      

Ive tried the following,

>>> "b" or "c" in xyz.get("a",{})
'b'

      

But I wondered if I could write this statement for both "b" and "c". Hope this makes sense.

+3


source to share


3 answers


or

does not work. (This may be the most frequently asked Python question on StackOverflow, but unfortunately, it is very difficult to find if you don't already know what the problem is ...) or

just takes two boolean expressions and returns something believable if either edit them So what you ask is whether it is "b"

true (it is) or "c" in xyz.get("a", {})

is it true (it may or may not be, but Python doesn't even need to be tested), so it returns you "b"

, which is true.

You can probably fix it with parentheses ("b" or "c") in xyz.get("a", {})

, but that's just as bad. It will evaluate ("b" or "c")

and get first "b"

, then it will check what's in the dict, ignoring "c"

.

The reason an equivalent sentence of a sentence makes sense in English is because you are implicitly asking "is it b in a dict or c in a dict"; Python won't let you leave it implicit, but you can always make it explicit:



"b" in xyz.get("a", {}) or "c" in xyz.get("a", {})`

      

If you want to do more than two of them (or if they are only known dynamically) then you will want to use any

and / or store xyz.get("a", {})

in a temporary variable instead of repeating like in utdemir's answer - or maybe even better using a set like in the answer Castres.

+2


source


any

and generator expressions are your friend:



>>> xyz = {"a":{"b":[1,2,3]}}
>>> any(i in xyz.get("a",{}) for i in ["b", "c"])
True

      

+5


source


You can use set.intersection

:

>>> bool({'b','c'}.intersection(xyz.get('a')))
True

      

the following example shows that its more efficient than any

:

:~$ python -m timeit "xyz = {'a':{'b':[1,2,3]}};any(i in xyz.get('a',{}) for i in ['b', 'c'])"
1000000 loops, best of 3: 0.932 usec per loop

:~$ python -m timeit "xyz = {'a':{'b':[1,2,3]}};bool({'b','c'}.intersection(xyz.get('a')))"
1000000 loops, best of 3: 0.649 usec per loop

      

But @abarnert's answer is the fastest in this case:

~$ python -m timeit "xyz = {'a':{'b':[1,2,3]}};'b' in xyz.get('a', {}) or 'c' in xyz.get('a', {})"
1000000 loops, best of 3: 0.325 usec per loop

      

+1


source







All Articles