patternpythonModerate
Flatten dictionary in Python (functional style)
Viewed 0 times
stylepythonfunctionaldictionaryflatten
Problem
I'm trying to learn how to write functional code with Python and have found some tutorials online. Please note that I know Python is not a promoter for functional programming. I just want to try it out. One tutorial in particular gives this as an exercise:
Write a function flatten_dict to flatten a nested dictionary by
joining the keys with . character.
So I decided to give it a try. Here is what I have and it works fine:
I'd like to know whether this is the best way to solve the problem in python. In particular, I really don't like to pass a list of previous keys to the recursive call.
Write a function flatten_dict to flatten a nested dictionary by
joining the keys with . character.
So I decided to give it a try. Here is what I have and it works fine:
def flatten_dict(d, result={}, prv_keys=[]):
for k, v in d.iteritems():
if isinstance(v, dict):
flatten_dict(v, result, prv_keys + [k])
else:
result['.'.join(prv_keys + [k])] = v
return resultI'd like to know whether this is the best way to solve the problem in python. In particular, I really don't like to pass a list of previous keys to the recursive call.
Solution
Your solution really isn't at all functional. You should return a flattened dict and then merge that into your current dictionary. You should also not modify the dictionary, instead create it with all the values it should have. Here is my approach:
Alternative which avoids yield
def flatten_dict(d):
def items():
for key, value in d.items():
if isinstance(value, dict):
for subkey, subvalue in flatten_dict(value).items():
yield key + "." + subkey, subvalue
else:
yield key, value
return dict(items())Alternative which avoids yield
def flatten_dict(d):
def expand(key, value):
if isinstance(value, dict):
return [ (key + '.' + k, v) for k, v in flatten_dict(value).items() ]
else:
return [ (key, value) ]
items = [ item for k, v in d.items() for item in expand(k, v) ]
return dict(items)Code Snippets
def flatten_dict(d):
def items():
for key, value in d.items():
if isinstance(value, dict):
for subkey, subvalue in flatten_dict(value).items():
yield key + "." + subkey, subvalue
else:
yield key, value
return dict(items())def flatten_dict(d):
def expand(key, value):
if isinstance(value, dict):
return [ (key + '.' + k, v) for k, v in flatten_dict(value).items() ]
else:
return [ (key, value) ]
items = [ item for k, v in d.items() for item in expand(k, v) ]
return dict(items)Context
StackExchange Code Review Q#21033, answer score: 19
Revisions (0)
No revisions yet.