【问题标题】:Create nested dictionary of arbitrary depth from list of lists containing keys of each level从包含每个级别的键的列表列表中创建任意深度的嵌套字典
【发布时间】:2018-04-01 12:17:25
【问题描述】:

Given 是一个包含任意长度列表的列表。每个列表都包含字典的一级键。

例子:

给定列表“DL”

DL = [['A1'],['A11','A12'],['B1'],['B11','B12']] # <- All entries are strings

我想创建一个具有以下结构的四级嵌套字典:

在 Python 表示法中:

D = {'A1': {'A11': {'B1': {'B11': [], 'B12': []}},
            'A12': {'B1': {'B11': [], 'B12': []}}}}

最后一级字典(B11、B12)的值应该是空列表。

【问题讨论】:

  • 能否将输出显示为实际字典而不是 ascii 艺术图像?
  • 到目前为止你尝试过什么?请给一些代码。
  • 如果它们是字符串,为什么不把它们变成字符串呢?当我试图回答你的问题时,我要做的第一件事就是插入一堆引号,这样输入就不会引发异常。这不是一个好的开始。

标签: python python-3.x list dictionary


【解决方案1】:

这是一个简单的递归函数。由于所有嵌套的字典都相同,因此该函数只需递归一次以构建子字典,然后使用copy.deepcopy 为每个值复制它。

import copy

def dictify(lst):
    if not lst:
        return []

    sub_dict = dictify(lst[1:])
    return {value: copy.deepcopy(sub_dict) for value in lst[0]}

dictify(DL) 的漂亮打印输出:

{'A1': {'A11': {'B1': {'B11': [], 'B12': []}},
        'A12': {'B1': {'B11': [], 'B12': []}}}}

【讨论】:

    【解决方案2】:

    我的解决方案遍历每个深度,从列表的“末尾”开始,然后遍历每个元素,将其分配给前一个深度的字典。

    DL = [['A1'],['A11','A12'],['B1'],['B11','B12']]
    DL_rev = DL[::-1] #reverse list - we want to create the smallest dicionaries first
    
    # Initialise dictionary where solution will be stored
    my_dictionary = {}
    
    # Calculate depth of dictionaries
    depth = len(DL)
    
    # Temporary dictionary
    temp = {}
    
    # First initialise the dictionary of empty arrays, into temp
    for k in DL_rev[0]:
        temp[k] = []
    
    # For each depth, create a new dictionary
    for i in range(1, depth):
        my_dictionary = {}
        # For each element, create an entry for it in the dictionary
        for j in DL_rev[i]:
            my_dictionary[j] = temp.copy()
        temp = my_dictionary.copy() #make a copy of the dictionary, for the next level up
    
    D = {'A1': {'A11': {'B1': {'B11': [], 'B12': []}},
            'A12': {'B1': {'B11': [], 'B12': []}}}}
    print(D)
    print(my_dictionary)
    print(D == my_dictionary)
    

    输出:

    {'A1': {'A12': {'B1': {'B12': [], 'B11': []}}, 'A11': {'B1': {'B12': [], 'B11': []}}}}
    {'A1': {'A12': {'B1': {'B12': [], 'B11': []}}, 'A11': {'B1': {'B12': [], 'B11': []}}}}
    True
    

    【讨论】:

    • 您的代码没有正确复制字典。其中一些字典是同一个字典对象;你必须使用copy.deepcopy(my_dictionary) 而不是my_dictionary.copy()。 (如果您尝试 my_dictionary['A1']['A11']['B1']['B11'] = 5 可以看到这一点 - 5 将出现在 my_dictionary 两次。)
    【解决方案3】:

    解决方案可以简化为从笛卡尔积创建字典树结构。

    这是基于collections.defaultdictitertools.product的解决方案。

    from collections import defaultdict
    from itertools import product
    
    DL = [['A1'],['A11','A12'],['B1'],['B11','B12']]
    
    rec_dd = lambda: defaultdict(rec_dd)
    d = rec_dd()
    
    for route in product(*DL):
        i = d[route[0]]
        for j in route[1:-1]:
            i = i[j]
        i[route[-1]] = []
    

    结果:

    defaultdict({'A1': defaultdict({'A11': defaultdict({'B1': defaultdict({'B11': [],
                                                                           'B12': []})}),
                                    'A12': defaultdict({'B1': defaultdict({'B11': [],
                                                                           'B12': []})})})})
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-29
      • 2021-06-18
      • 1970-01-01
      • 2020-05-10
      • 1970-01-01
      相关资源
      最近更新 更多