【问题标题】:How to get keys from nested dictionary of arbitrary length in Python如何从Python中任意长度的嵌套字典中获取键
【发布时间】:2014-12-12 06:26:43
【问题描述】:

我在 python 中有一个字典对象。我们称之为dict。这个对象可能包含另一个字典,而另一个字典又可能包含另一个字典等等。

     dict = { 'k': v, 'k1': v1, 'dict2':{'k3': v3, 'k4':v4} , 'dict3':{'k5':v5, dict4:{'k6':v6}}}

这只是一个例子。最外层字典的长度可以是任何东西。我想通过以下两种方式从此类字典对象中提取键:

  1. 获取唯一键的列表。

    [k,k1,k2,k3,k4,k5,k6]
    
  2. 获取键列表及其父关联字典,如下所示:

    outer_dict_keys = [k ,dict2, dict3]
    dict2_keys = [k3,k4]
    dict3_keys = [k5, dict4]
    dict4_keys = [k6]
    

最外层字典dict 长度总是在变化,所以我不能硬编码任何东西。

实现上述结果的最佳方法是什么?

【问题讨论】:

    标签: python-3.x recursion dictionary nested


    【解决方案1】:

    混合使用迭代和尾递归。在引用未定义的名称、使间距一致并从第一个结果中删除“k2”之后,我想出了下面的代码。 (针对 3.4 编写和测试,它应该在任何 3.x 上运行,并且可能在 2.7 上运行。)要记住的关键是 dicts 的迭代顺序本质上是随机的,并且随着每次运行而变化。此处所做的递归以深度优先而不是广度优先顺序访问子字典。对于dict0,两者是一样的,但是如果dict4嵌套在dict2而不是dict3中,就不会了。

    dict0 = {'k0': 0, 'k1': 1, 'dict2':{'k3': 3, 'k4': 4},
             'dict3':{'k5': 5, 'dict4':{'k6': 6}}}
    
    def keys(dic, klist=[]):
        subdics = []
        for key in sorted(dic):
            val = dic[key]
            if isinstance(val, dict):
                subdics.append(val)
            else:
                klist.append(key)
        for subdict in subdics:
            keys(subdict, klist)
        return klist
    
    result = keys(dict0)
    print(result, '\n', result == ['k0','k1','k3','k4','k5','k6'])
    
    def keylines(dic, name='outer_dict', lines=[]):
        vals = []
        subdics = []
        for key in sorted(dic):
            val = dic[key]
            if isinstance(val, dict):
                subdics.append((key,val))
            else:
                vals.append(key)
        vals.extend(pair[0] for pair in subdics)
        lines.append('{}_keys = {}'.format(name, vals))
        for subdict in subdics:
            keylines(subdict[1], subdict[0], lines)
        return lines
    
    result = keylines(dict0)
    for line in result:
        print(line,)
    print()
    expect = [
            "outer_dict_keys = ['k0', 'k1', 'dict2', 'dict3']",
            "dict2_keys = ['k3', 'k4']",
            "dict3_keys = ['k5', 'dict4']",
            "dict4_keys = ['k6']"]
    for actual, want in zip(result, expect):
        if actual != want:
            print(want)
            for i, (c1, c2) in enumerate(zip(actual, want)):
                if c1 != c2:
                    print(i, c1, c2)
    

    【讨论】:

    • 这太棒了。谢谢特里!
    猜你喜欢
    • 2022-01-07
    • 1970-01-01
    • 2019-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-10
    • 1970-01-01
    • 2013-02-19
    相关资源
    最近更新 更多