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.
source to share
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.
source to share
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
source to share