Reputation: 301
There are lots of great solutions to flattening a Python dictionary, but most recursive methods seem to automatically add a 'parent key' to key when the value is a dictionary (regardless of whether the nested key is-so far- unique) - like in this solution. This is the flattening function that automatically adds the parent key to the key when nested.
def flatten_dict(item, parent_key='', sep='_'):
final = []
for key, val in item.items():
new_key = parent_key + sep + key if parent_key else key
if isinstance(val, dict):
final.extend(flatten_dict(val, parent_key=new_key).items())
else:
final.append((new_key, val))
return dict(final)
I have tried to pass a set of 'used keys' through to flatten_dict and still get parent key added to key (I imagine that they are being passed through multiple times in the recursion and being marked as used). Is there a way using recursion to only add parent_key to key if key is not unique?
For example:
flatten_dict({'a':1, 'b': {'a': 1, 'c': 1}})
returns:
{'a': 1, 'b_a':1, 'b_c': 1}
But ideally I'd like:
{'a': 1, 'b_a': 1, 'c': 1} # because 'c' is unique
Thanks for any help!
Upvotes: 0
Views: 282
Reputation: 1034
I recommend using an "accumulator" dict as input parameter instead of a list. This enables efficient lookup whether the key already exists.
def flat_dict(d, acc=None, parent_key=None, sep="_"):
out = dict() if acc is None else acc
for k, v in d.items():
if type(v) is dict:
flat_dict(v, out, parent_key=str(k))
else:
if k in out:
k = parent_key + sep + str(k)
out[k] = v
return out
If all your keys are already strings, you can of course drop the str
casts.
Upvotes: 2