Search code examples
pythondictionarylist-comprehensiondictionary-comprehension

Unpack dict from list where key is not None


Trying to unpack the dicts which are not None from a list:

In [4]: unpack_dict = [{'key': 'a'}, {'key_2': 'b'}, None]

Tried a dict comprehension

In [5]: {key: value for (key, value) in unpack_dict if (key, value) is not None}
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-5-ec0e44b95586> in <module>()
----> 1 {key: value for (key, value) in unpack_dict if (key, value) is not None}

<ipython-input-5-ec0e44b95586> in <dictcomp>(.0)
----> 1 {key: value for (key, value) in unpack_dict if (key, value) is not None}

ValueError: not enough values to unpack (expected 2, got 1)

And a list comprehension:

In [6]: {**[x for x in [unpack_dict] if x is not None]}
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-6-ac36898d39a1> in <module>()
----> 1 {**[x for x in [unpack_dict] if x is not None]}

TypeError: 'list' object is not a mapping

Expected result:

{'key': 'a', 'key_2': 'b'}

What is the right syntax?


Solution

  • You are trying to unpack either a dictionary or None to two variables (key and value). You can't unpack either type in this way. None is not iterable, and iteration over a dict would yield only the keys, not the values.

    Loop over the dictionary items if there is a dictionary, otherwise loop over an empty sequence, and unpack the iteration results:

    {key: value for d in unpack_dict for key, value in (d.items() if d else ())}
    

    The d.items() if d else () expression produces either an iterable of (key, value) pairs from a (non-empty) dictionary, or an empty tuple (causing that nested iteration to stop immediately).

    Demo:

    >>> unpack_dict = [{'key': 'a'}, {'key_2': 'b'}, None]
    >>> {key: value for d in unpack_dict for key, value in (d.items() if d else ())}
    {'key': 'a', 'key_2': 'b'}