flattening a dict

Arnaud Delobelle arnodel at googlemail.com
Sun Feb 17 07:51:37 EST 2008


On Feb 17, 12:18 pm, Terry Jones <te... at jon.es> wrote:
> Hi Arnaud & Benjamin
>
> Here's a version that's a bit more general. It handles keys whose values
> are empty dicts (assigning None to the value in the result), and also dict
> keys that are not strings (see the test data below). It's also less
> recursive as it only calls itself on values that are dicts.
>
> But.... it returns a dict whose keys are tuples. You then need to decide
> what to do with this. Hence the helper function strdictflatten for the case
> when all dict keys can be converted to str.
>
> As I told Arnaud in email, I greatly prefer his version for its elegance.
>
> Terry
>
> def dictflatten(d, prefix=None):
>     result = {}
>     if prefix is None: prefix = tuple()
>     for k, v in d.iteritems():
>         key = prefix + (k,)
>         if isinstance(v, dict):
>             if v:
>                 result.update(dictflatten(v, key))
>             else:
>                 result[key] = None
>         else:
>             result[key] = v
>     return result

It's nice to do it this way I think.  Here I post a generator-powered
version of the same idea.

from itertools import chain

def flattendict(d):
    def gen(d, pfx=()):
        return chain(*(gen(v, pfx+(k,)) if isinstance(v, dict)
                       else ((pfx+(k,), v),)
                       for k, v in d.iteritems()))
    return dict(gen(d))

BTW, I keep using the idiom itertools.chain(*iterable).  I guess that
during function calls *iterable gets expanded to a tuple.  Wouldn't it
be nice to have an equivalent one-argument function that takes an
iterable of iterables and return the 'flattened' iterable?

--
Arnaud




More information about the Python-list mailing list