flattening a dict

Benjamin musiccomposition at gmail.com
Thu Feb 21 23:08:48 EST 2008


On Feb 21, 9:13 pm, George Sakkis <george.sak... at gmail.com> wrote:
> On Feb 21, 8:04 pm, Benjamin <musiccomposit... at gmail.com> wrote:
>
>
>
> > On Feb 17, 6:18 am, 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
>
> > > def strdictflatten(d, sep='/'):
> > >     return dict((sep.join(map(str, k)), v) for k, v in dictflatten(d).iteritems())
>
> > Thanks. This is great. Now, how would I restrict the depth of the
> > flattening? For example, what if I just wanted something like this:
> > {
> > "mays" : {"eggs" : "spam"},
> > "jam" : {"soda" : "soda/love" : "dump"},
> > lamba" : 23}
>
> > They are left alone up the to second level of recursion.
>
> Why don't you do your homework on your own for a change ? Or at least
> pretend you're even trying ?
<excuseme>
Here's a attempt:
def dictflatten(d, prefix=None, depth=2, cur_depth=0):
    result = {}
    if prefix is None: prefix = tuple()
    if isinstance(prefix, basestring): prefix = (prefix,)
    cur_depth += 1
    for k, v in d.iteritems():
        key = prefix + (k,)
        print key, cur_depth
        if isinstance(v, dict):
            if v:
                if cur_depth >= depth:
                    result.update(dictflatten(v, key, depth,
cur_depth))
                else:
                    result.update(dictflatten(v, k, depth, cur_depth))
            else:
                result[key] = None
        else:
            result[k] = v
    return result
</excuseme>



More information about the Python-list mailing list