I needed to flatten a dictionary today. Meaning I wanted:
{'_id': 0, 'sub': {'a': 1, 'b':2}}
to become:
{'_id': 0, 'a':1, 'b':2}
So I thought I could be clever and pull off the following one-liner.
x = dict(_id=0, sub=dict(a=1, b=2))
y = x.pop('sub').update(x) # incorrect result
This results in y = None
.
So I obviously resorted to:
x = dict(_id=0, sub=dict(a=1, b=2))
y = x.pop('sub')
y.update(x) # correct result
Setting "good expressive coding practices" asside for a moment, I would like to understand why the One-liner approach above yields None
. I would have thought that x.pop('sub') would have resulted in a temporary dict on a stack somewhere and the original x dict would be immediately updated. Then the stack object would receive the next method in the chain which is the update. This obviously does not seem to be the case.
For the communities better understanding (and clearly mine) - how does python resolve the one-liner and result in None ?
The .update()
method returns None
, because it alters the affected dictionary in-place. .pop()
does return the popped value, the nested dictionary.
You are updating the contained dict
, why not update the parent dict
instead?
x.update(x.pop('sub'))
Result:
>>> x = dict(_id=0, sub=dict(a=1, b=2))
>>> x.update(x.pop('sub'))
>>> x
{'a': 1, '_id': 0, 'b': 2}
Or you could do this recursively:
def inplace_flatten(d):
keys = list(d.keys())
for k in keys:
if isinstance(d[k], dict):
inplace_flatten(d[k])
d.update(d.pop(k))
因为y
获得dict.update()
的结果,所以它为None
。
This should do the trick
def flatten(d, answer=None):
if answer == None:
answer = {}
if not d:
return answer
else:
for k in d:
if isinstance(d[k], dict):
flatten(d[k], answer)
else:
answer[k] = d[k]
return answer
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.