python - 平面嵌套字典,其中新键将是所有嵌套键的元组

标签 python python-3.x

我有一个这样的字典:

previous_dict = {
    'dict_1': 'dict_1',
    'dict_2': {
        'dict_2_1': 'dict_2_1',
        'dict_2_2': 'dict_2_2'
    },
    'dict_3': 3,
    'dict_4': None,
    'dict_5': dict()
}

我编写了一个函数,将字典中的所有键作为元组进行平铺,其输出为:

previously_expected_dict = {}
for key, value in previous_dict.items():
    if type(value) == dict:
        for k, v in value.items():
            previously_expected_dict[(key, k)] = v
    else:
        previously_expected_dict[(key,)] = value

输出:

print(previously_expected_dict)
{
    ('dict_1',): 'dict_1',
    ('dict_2', 'dict_2_1'): 'dict_2_1',
    ('dict_2', 'dict_2_2'): 'dict_2_2',
    ('dict_3',): 3,
    ('dict_4',): None
}

dict_5 is discarded as it does not have any value


现在要求已经改变,字典可以有任意数量的嵌套

new_dict = {
    'dict_1': {
        'dict_1_1': {
            'dict_1_1_1': 'dict_1_1_1',
            'dict_1_1_2': 'dict_1_1_2'
        }
    },
    'dict_2': {
        'dict_2_1': 'dict_2_1',
        'dict_2_2': 'dict_2_2'
    },
    'dict_3': 'dict_3',
    'dict_4': dict()
}

到目前为止我已经尝试过的代码

def make_flat(my_dict):
    nd = dict()
    keys = []

    def loop_me(value):
        nonlocal keys
        if isinstance(value, dict):
            for k, v in value.items():
                keys.append(k)
                loop_me(v)
        else:
            nd[tuple(keys)] = value
            keys.pop(-1)

    loop_me(my_dict)
    return nd


print(make_flat(new_dict))

但是我收到了元组中的额外 key

{
    ('dict_1', 'dict_1_1', 'dict_1_1_1'): 'dict_1_1_1',  # Perfect
    ('dict_1', 'dict_1_1', 'dict_1_1_2'): 'dict_1_1_2',  # Perfect
    ('dict_1', 'dict_1_1', 'dict_2', 'dict_2_1'): 'dict_2_1',  # Error, Expected is: ('dict_2', 'dict_2_1')
    ('dict_1', 'dict_1_1', 'dict_2', 'dict_2_2'): 'dict_2_2',  # Error, Expected is: ('dict_2', 'dict_2_2')
    ('dict_1', 'dict_1_1', 'dict_2', 'dict_3'): 'dict_3'  # Error, Expected is: ('dict_3',)
}

最终预期输出:

output = {
    ('dict_1', 'dict_1_1', 'dict_1_1_1'): 'dict_1_1_1',
    ('dict_1', 'dict_1_1', 'dict_1_1_2'): 'dict_1_1_2',
    ('dict_2', 'dict_2_1'): 'dict_2_1',
    ('dict_2', 'dict_2_2'): 'dict_2_2',
    ('dict_3',): 'dict_3'
}

我尝试用for循环和递归函数编写,失败。

最佳答案

您可以使用递归:

def flatten(d, c = []):
  for a, b in d.items():
    if not isinstance(b, dict):
       yield (tuple(c+[a]), b)
    else:
       yield from flatten(b, c+[a])

print(dict(flatten(previous_dict)))

输出:

{('dict_1',): 'dict_1', ('dict_2', 'dict_2_1'): 'dict_2_1', ('dict_2', 'dict_2_2'): 'dict_2_2', ('dict_3',): 3, ('dict_4',): None}

使用new_dict:

{('dict_1', 'dict_1_1', 'dict_1_1_1'): 'dict_1_1_1', ('dict_1', 'dict_1_1', 'dict_1_1_2'): 'dict_1_1_2', ('dict_2', 'dict_2_1'): 'dict_2_1', ('dict_2', 'dict_2_2'): 'dict_2_2', ('dict_3',): 'dict_3'}

关于python - 平面嵌套字典,其中新键将是所有嵌套键的元组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55766114/

相关文章:

python - 如何在 Maya 中使用 Def Function 字符串

python - 模板中的 django request.session.user

python - 如何从Python字典键在Excel中创建标题

python - Python中基于字符串/整数序列的聚类和距离/相异矩阵

python - 使用占位符删除文件

python - 几个类似的正则表达式。更快的方法来做到这一点?

python - 对于 PIL.ImageFilter.GaussianBlur 如何使用内核以及半径参数与标准偏差有关吗?

encoding - Python 3 中的流/字符串/字节数组转换

python - 如何检查列表中的所有元素是否都存在于 pandas 列中

python - 如何更改选项卡标题框的大小和 ttk 笔记本选项卡的字体?