首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >扁平嵌套字典,其中新键将是所有嵌套键的元组

扁平嵌套字典,其中新键将是所有嵌套键的元组
EN

Stack Overflow用户
提问于 2019-04-20 02:21:16
回答 3查看 139关注 0票数 2

我有一句话是这样的:

代码语言:javascript
复制
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()
}

我已经写了一个函数,用所有键作为元组来扁平化字典,输出如下:

代码语言:javascript
复制
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

输出:

代码语言:javascript
复制
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被丢弃,因为它没有任何值

现在需求已经改变了,dict可以有任意数量的嵌套

代码语言:javascript
复制
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()
}

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

代码语言:javascript
复制
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))

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

代码语言:javascript
复制
{
    ('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',)
}

最终预期输出:

代码语言:javascript
复制
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循环和递归函数编写代码,但失败了。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2019-04-20 02:24:50

您可以使用递归:

代码语言:javascript
复制
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)))

输出:

代码语言:javascript
复制
{('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

代码语言:javascript
复制
{('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'}
票数 2
EN

Stack Overflow用户

发布于 2019-04-20 02:37:46

您可以使用一个函数来迭代dict项,并将键预先添加到递归调用返回的子键的元组中:

代码语言:javascript
复制
def flatten(d):
    for k, v in d.items():
        if isinstance(v, dict):
            for s, i in flatten(v):
                yield (k, *s), i
        else:
            yield (k,), v

因此dict(flatten(new_dict))返回:

代码语言:javascript
复制
{('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'}
票数 2
EN

Stack Overflow用户

发布于 2019-04-20 02:33:37

我已经使用了deep变量来确定和纠正键,make_flat函数返回您想要的输出,但是@Ajax1234做得更清楚。

代码语言:javascript
复制
def make_flat(dict_):
    new_dict = dict()
    keys = []

    def loop_recursively(value, deep=0):
        nonlocal keys
        if isinstance(value, dict):
            deep += 1
            for k, v in value.items():
                keys.append(k)
                loop_recursively(v, deep)
            else:
                deep -= 1
        else:
            keys = keys[-deep:]
            new_dict[tuple(keys)] = value
            keys.pop(-1)

    loop_recursively(dict_)
    return new_dict
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55766114

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档