我从另一个脚本收到一个包含各种类型的字典,特别是其他字典或可能包含其他字典作为值的列表。
现在我要做的是创建一个单一的平面字典。键可能在封装的字典中多次出现。对我来说,最里面的键包含最新信息,所以我认为 dict.update
是消化“内部”字典时应用的正确例程。 “内部”字典是指具有最外层字典某些值的字典。
现在,我了解了如何将字典扁平化 1 级。我努力将其扁平化到任意多个级别。
我正在处理的字典类型的一个简单示例是:
d = {1: {6: {7: {2: {'a'}}}}, 2: 'b', 3: {4: {2: 'c'}}, 5: ['a', 'b', {1: 'a'}]}
我的尝试适用于单一深度级别:
dd = dict()
for k, v in d.items():
if isinstance(v, dict):
dd.update(v)
elif isinstance(v, list):
for el in v:
if isinstance(el, dict):
dd.update(el)
dd[k] = [el for el in v if not isinstance(el, dict)]
else:
dd[k] = v
这给了我:
Out[56]: {6: {7: {2: {'a'}}}, 2: 'b', 4: {2: 'c'}, 1: 'a', 5: ['a', 'b']}
它应该给出的是:
{2: 'a', 5: ['a', 'b']}
注意键 2
的值:'c'
而不是(我现在得到的)'b'
。这应该是因为键 2
的最内层值是 'c'
而不是 'b'
。
我不只是想获得一个功能代码(尽管这可以让我继续工作),但我想了解如何在 python 中解决这样的问题。我不得不承认我在这里有点迷路......
非常感谢任何帮助!
最佳答案
您可以将递归与生成器一起使用,并保留一个计数器来确定深度:
d = {1: {6: {7: {2: {'a'}}}}, 2: 'b', 3: {4: {2: 'c'}}, 5: ['a', 'b', {1: 'a'}]}
def flatten(_d, _depth = 0):
for a, b in _d.items():
if isinstance(b, list):
yield [a, [i for i in b if not isinstance(i, dict)], _depth]
for c in b:
if isinstance(c, dict):
yield from flatten(c, _depth+1)
elif isinstance(b, dict):
yield from flatten(b, _depth+1)
else:
yield [a, b, _depth]
_result = {}
for a, b, c in flatten(d):
if a not in _result:
_result[a] = [b, c]
else:
if _result[a][-1] < c:
_result[a] = [b, c]
print({a:b for a, [b, c] in _result.items()})
输出:
{2: {'a'}, 5: ['a', 'b'], 1: 'a'}
关于python - 展平任意深度的字典,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53989229/