sparkandshine sparkandshine - 6 months ago 7
Python Question

How do I get the first value from a list of keys in a concrete way in Python?

There is a dict (say

d
).
dict.get(key, None)
returns
None
if
key
doesn't exist in
d
.

How do I get the first value (i.e.,
d[key]
is not
None
) from a list of keys (some of them might not exist in
d
)?


This post, Pythonic way to avoid “if x: return x” statements, provides a concrete way.

for d in list_dicts:
for key in keys:
if key in d:
print(d[key])
break


I use xor operator to acheive it in one line, as demonstrated in,

# a list of dicts
list_dicts = [ {'level0' : (1, 2), 'col': '#ff310021'},
{'level1' : (3, 4), 'col': '#ff310011'},
{'level2' : (5, 6), 'col': '#ff312221'}]

# loop over the list of dicts dicts, extract the tuple value whose key is like level*
for d in list_dicts:
t = d.get('level0', None) or d.get('level1', None) or d.get('level2', None)
col = d['col']

do_something(t, col)


It works. In this way, I just simply list all options (
level0
~
level3
). Is there a better way for a lot of keys (say, from
level0
to
level100
), like list comprehensions?

Answer

This line:

x, y = d.get('level0', None) or d.get('level1', None) or d.get('level2', None)

Is basically mapping a list of ['level0', 'level1', 'level2'] to d.get (None is already the default value; there's no need to explicitly state it in this case). Next, you want to choose the one that doesn't map to None, which is basically a filter. You can use the map() and filter() built-in functions (which are lazy generator-like objects in Python 3) and call next() to get the first match:

list_dicts = [  {'level0' : (1, 2), 'col': '#ff310021'},
                {'level1' : (3, 4), 'col': '#ff310011'},
                {'level2' : (5, 6), 'col': '#ff312221'}]
>>> l = 'level0', 'level1', 'level2'
>>> for d in list_dicts:
...     print(next(filter(None, map(d.get, l))))
...
(1, 2)
(3, 4)
(5, 6) 
Comments