B
Benjamin
<excuseme>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 ?
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>