压扁任意深度的二进制

Tim*_*imC 4 python recursion dictionary flatten

我从另一个脚本收到一个包含各种类型的字典,特别是其他可能包含其他字典作为值的字典或列表.

现在我想要做的是创建一个单一的平面字典.密钥可能在封装的字典中多次出现.对我来说,最内层的关键信息包含最新信息,所以我认为dict.update在消化"内在"字典时适用的是正确的例程."内部"字典我的意思是一本带有最外层字典值的字典.

现在,我理解如何将字典压平1级.我挣扎着用任意多层来压扁它.

我正在处理的字典类型的一个简单示例示例是:

d = {1: {6: {7: {2: {'a'}}}}, 2: 'b', 3: {4: {2: 'c'}}, 5: ['a', 'b', {1: 'a'}]}
Run Code Online (Sandbox Code Playgroud)

我的尝试适用于单一深度:

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
Run Code Online (Sandbox Code Playgroud)

这给了我:

Out[56]:  {6: {7: {2: {'a'}}}, 2: 'b', 4: {2: 'c'}, 1: 'a', 5: ['a', 'b']}
Run Code Online (Sandbox Code Playgroud)

它应该给予的是:

{2: 'a', 5: ['a', 'b']}
Run Code Online (Sandbox Code Playgroud)

注意键的值2:'c'而不是(我现在得到的)'b'.这应该是因为密钥的最内层值2'c'和不是'b'.

我不只是想获得一个正常运行的代码(虽然这将允许我继续工作)但我想了解如何在python中解决这样的问题.我不得不承认我在这里迷失了一点......

任何帮助是极大的赞赏!

Aja*_*234 6

您可以对发生器使用递归并保留计数器以确定深度:

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()})
Run Code Online (Sandbox Code Playgroud)

输出:

{2: {'a'}, 5: ['a', 'b'], 1: 'a'}
Run Code Online (Sandbox Code Playgroud)