迭代嵌套字典 returns 仅第一个元素

Iterating over nested dictionary returns only first element

我有这个嵌套字典(“字典的字典”)

source = {
    "OuterVal0": {"InnerVal": [10, 21, 96],"InnerVal2": [100, 91, 71]},
    "OuterVal1": {"InnerVal": [21, 19, 76],"InnerVal2": [1, 1, 1]},
    "OuterVal2": {"InnerVal": [1, 1, 96],"InnerVal2": [10, 9, 7]},
    "OuterVal3": {"InnerVal": [0, 2, 6],"InnerVal2": [1, 911, 718]},
    "OuterVal4": {"InnerVal": [12, 13, 9],"InnerVal2": [1000, 910, 701]},
    "OuterVal5": {"InnerVal": [110, 211, 961],"InnerVal2": [10, 911, 918]},     
}

我想创建一个新的,它由与内部值相关联的外键组成(见下面的预期输出) 我使用这个递归函数:

def myPrint(d, key=""):
    output = {}
    for k, v in d.items():
        i = 0
        if isinstance(v, dict):
          return  myPrint(v, k)
        else:
            for  value in d.values():
                newkey = (f"{i}_{key}")
                output[newkey] = value
                i += 1
    return output

但是当我尝试打印时:

print(myPrint(source))

我明白了(只处理了第一个字典:

# {'0_OuterVal0': [10, 21, 96], '1_OuterVal0': [100, 91, 71]}

但我想要这样的东西(处理所有词典)

"""
Expected output
{'0_OuterVal0': [10, 21, 96], '1_OuterVal0': [100, 91, 71]}
{'0_OuterVal1':[21, 19, 76], '1_OuterVal1': [1, 1, 1]}
.
.
.
{'0_OuterVal5':  [110, 211, 961], '1_OuterVal5': [10, 911, 918]}

"""

我做错了什么?

非常感谢您的帮助。

使用调试器逐步执行代码会对您有所帮助:

当您调用 myPrint(source) 并进入 for 循环时,您确实递归地调用了您的函数,但您没有将第一个嵌套字典添加到输出中,而是使用了 return 关键字。所以用第一个键创建的字典被返回,这就是你的函数的结尾。

如果你的函数的目的是打印,并且你想保留你原来的代码结构,你可以使用这个:

def myPrint(d, key=""):
    output = {}
    lines = ""
    for k, v in d.items():
        i = 0
        if isinstance(v, dict):
            lines += str(myPrint(v, k)) + '\n'
        else:
            for value in d.values():
                newkey = (f"{i}_{key}")
                output[newkey] = value
                i += 1

    return output if lines == "" else lines

您想要的输出可以更简单地作为列表理解获得:

output = [{f'0_OuterVal{i}': v['InnerVal'], f'1_OuterVal{i}': v['InnerVal2']}
          for i, (k, v) in enumerate(source.items())]

这将创建一个包含您指定的键和值的字典列表。

问题是,当您第一次调用 return myPrint(v, k) 时,您计算第一个字典的值然后 return 而不是继续 for 循环中的其他值。

将函数更改为:

def myPrint(d, key=""):
    output = {}
    for k, v in d.items():
        i = 0
        if isinstance(v, dict):
          output.update(myPrint(v, k))
        else:
            for  value in d.values():
                newkey = (f"{i}_{key}")
                output[newkey] = value
                i += 1
    return output

会return一本大字典,给你举个例子:

{'0_OuterVal0': [10, 21, 96], '1_OuterVal0': [100, 91, 71],
 '0_OuterVal1': [21, 19, 76], '1_OuterVal1': [1, 1, 1],
 '0_OuterVal2': [1, 1, 96], '1_OuterVal2': [10, 9, 7],
 '0_OuterVal3': [0, 2, 6], '1_OuterVal3': [1, 911, 718],
 '0_OuterVal4': [12, 13, 9], '1_OuterVal4': [1000, 910, 701],
 '0_OuterVal5': [110, 211, 961], '1_OuterVal5': [10, 911, 918]}

但是,函数可以很好地打包成 non-recursive 方式,如下所示:

output = [{f'{ii}_{k}': vv  for (k, v) in source.items() for ii, (kk, vv) in enumerate(v.items())}]