简体   繁体   English

从元组列表创建嵌套字典

[英]Creating nested dictionary from list of tuples

Given a list called outlines containing tuples: (level, title), create a nested dictionary with depth based on the level and key value based on the title.给定一个包含元组的称为轮廓的列表:(级别,标题),创建一个嵌套字典,其深度基于级别,键值基于标题。

Example list:示例列表:
[(1, Abstract) [(1,摘要)
(2, Background) (2、背景)
(2, Methods) (2、方法)
(2, Results) (2、结果)
(3, Statistics) (3、统计)
(3, Images) (3, 图片)
(1, Introduction)] (一、简介)】

This should output:这应该是 output:

{
"Abstract": {
    "Background": {}, 
    "Methods": {}, 
    "Results": {
        "Statistics": {},
        "Images": {}
    }
},
"Introduction": {}
}

So far I've tried a recursive solution but so far has resulted in untraceable erroneous behavior.到目前为止,我已经尝试了一个递归解决方案,但到目前为止已经导致无法追踪的错误行为。 This is the best solution I've come up with so far, but I have trouble preventing duplicates in different levels due to the predefined for-loop:这是迄今为止我提出的最佳解决方案,但由于预定义的 for 循环,我无法防止不同级别的重复:

def structure(outlines, current_level=1, previous_title=''):
    section = dict()
    for i, (level, title) in enumerate(outlines):
        if level == current_level:
            section[title] = {}
            previous_title = title
        elif level > current_level:
            section[previous_title] = structure(outlines[i:], level)
        elif level < current_level:
            pass # Unknown
    return section

Any tips?有小费吗?

Assuming that the order matters then this would work:假设顺序很重要,那么这将起作用:

generator = [
    (1, 'Abstract'),
    (2, 'Background'),
    (2, 'Methods'),
    (2, 'Results'),
    (3, 'Statistics'),
    (3, 'Images'),
    (1, 'Introduction')
]

# keep track of latest place in the dict
current_tree = []

# dict that you want to generate
d = {}

for i, value in generator:

    # if this, then you are at the highest level
    # so just add your value at the top
    if current_tree==[] or i==1:
        d[value] = {}
        current_tree = [value]

    # otherwise go back in the tree and add your value
    else:

        tmp_d = d
        for key in current_tree[:i-1]:
            tmp_d = tmp_d[key]

        tmp_d[value] = {}

        current_tree = current_tree[:i] + [value]

This returns:这将返回:

{'Abstract': {'Background': {'Images': {}, 'Statistics': {}},
              'Methods': {},
              'Results': {}},
 'Introduction': {}}

This is my recursive solution:这是我的递归解决方案:

import json
inlist = [
    (1, "Abstract"),
    (2, "Background"),
    (2, "Methods"),
    (2, "Results"),
    (3, "Statistics"),
    (3, "Images"),
    (1, "Introduction"),
]

out = dict()
# IMPORTANT: Dictionaries are ordered in Python 3.6 (under the CPython implementation at least) unlike in previous incarnations.
def addElem(dest_level, new_elem, current_container, current_level=1):
    # list(current_container.keys())[-1] gets the most recently added element at the current level.
    if (current_level < dest_level):
        addElem(dest_level, new_elem, current_container[list(current_container.keys())[-1]], current_level+1)
    else:
        current_container[new_elem] = dict()

for el in inlist:
    addElem(el[0], el[1], out)

print(json.dumps(out, indent=2))

Output: Output:

{
  "Abstract": {
    "Background": {},
    "Methods": {},
    "Results": {
      "Statistics": {},
      "Images": {}
    }
  },
  "Introduction": {}
}

We already have a working solution thanks to John R.感谢 John R,我们已经有了一个可行的解决方案。 Paul, but I wanted a solution which doesn't rely on dictionaries being ordered.保罗,但我想要一个不依赖于订购字典的解决方案。 As an added bonus, the solution is non-recursive (although John R. Paul's solution is tail-recursive and thus can be trivially rewritten to use a while loop).作为额外的奖励,该解决方案是非递归的(尽管 John R。Paul 的解决方案是尾递归的,因此可以简单地重写以使用while循环)。

def add_all(generator_of_pairs):
    stack = [{}]
    for (level, name) in generator_of_pairs:
        del stack[level:]
        new_dict = {}
        stack[level - 1][name] = new_dict
        stack.append(new_dict)
    return stack[0]

Note that this solution assumes that nesting levels cannot increase by more than 1 from 1 element to the next - but hopefully it should be obvious that this assumption is necessary.请注意,此解决方案假定嵌套级别从 1 个元素到下一个元素的增加不能超过 1 - 但希望很明显,这个假设是必要的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM