Python:将元组列表转换为嵌套字典的字典

时间:2016-09-12 19:52:43

标签: python list python-3.x dictionary tuples

所以我手上有点问题。我有一个元组列表(由一个级别号和消息组成),最终将成为一个HTML列表。我的问题是,在此之前,我想将元组值转换为嵌套字典的字典。所以这是一个例子:

# I have this list of tuples in format of (level_number, message)
tuple_list = [(1, 'line 1'), (2, 'line 2'), (3, 'line 3'), (1, 'line 4')]

# And I want to turn it into this
a_dict = {
    'line 1': {
        'line 2': {
            'line 3': {}
        }
    }, 
    'line 4': {}
}

任何帮助都会受到赞赏,只要它是有效的Python 3.谢谢!

2 个答案:

答案 0 :(得分:2)

正如我在评论中指出的那样,如果你对它有任何控制权,你应该强烈考虑改变你的传入数据结构。顺序列表的元组绝对不适合你在这里做的事情。但是,如果你把它当作一棵树来对待它是可能的。让我们构建一个(理智的)数据结构,用

解析它
class Node(object):
    def __init__(self, name, level, parent=None):
        self.children = []
        self.name = name
        self.level = level
        self.parent = parent

    def make_child(self, othername, otherlevel):
        other = self.__class__(othername, otherlevel, self)
        self.children.append(other)
        return other

现在,您应该能够以合理的方式迭代数据结构

def make_nodes(tuple_list):
    """Builds an ordered grouping of Nodes out of a list of tuples
    of the form (level, name). Returns the last Node.
    """

    curnode = Node("root", level=-float('inf'))
    # base Node who should always be first.

    for level, name in tuple_list:
        while curnode.level >= level:
            curnode = curnode.parent
            # if we've done anything but gone up levels, go
            # back up the tree to the first parent who can own this
        curnode = curnode.make_child(name, level)
        # then make the node and move the cursor to it
    return curnode

一旦你的结构完成,你可以迭代它。如果你先深度优先或广度优先,那么这里没什么关系,所以让我们做一个DFS只是为了便于实现。

def parse_tree(any_node):
    """Given any node in a singly-rooted tree, returns a dictionary
    of the form requested in the question
    """

    def _parse_subtree(basenode):
        """Actually does the parsing, starting with the node given
        as its root.
        """

        if not basenode.children:
            # base case, if there are no children then return an empty dict
            return {}
        subresult = {}
        for child in basenode.children:
            subresult.update({child.name: _parse_subtree(child)})
        return subresult

    cursor = any_node
    while cursor.parent:
        cursor = cursor.parent
        # finds the root node
    result = {}
    for child in cursor.children:
        result[child.name] = _parse_subtree(child)
    return result

然后输入您的元组列表 et voila

tuple_list = [(1, 'line 1'), (2, 'line 2'), (3, 'line 3'), (1, 'line 4')]

last_node = make_nodes(tuple_list)
result = parse_tree(last_node)
# {'line 1': {'line 2': {'line 3': {}}}, 'line 4': {}}

答案 1 :(得分:0)

假设你只有三个级别,那么会发生以下情况:

tuple_list = [(1, 'line 1'), (2, 'line 2'), (3, 'line 3'), (1, 'line 4')]

a_dict = {}

for prio, key in tuple_list:
    if prio == 1:
        a_dict[key] = {}
        first_level = key
    if prio == 2:
        a_dict[first_level][key] = {}
        second_level = key
    if prio == 3:
        a_dict[first_level][second_level][key] = {}
    # So on ...
print a_dict

这也假设层次结构按顺序列出,意味着级别1,级别1',级别2,级别3将是级别1的单个字典,以及级别1' - >>的层级顺序。 2级 - >级别3.以下

tuple_list = [(1, 'line 5'), (1, 'line 1'), (2, 'line 2'), (3, 'line 3'), (1, 'line 4')]

会产生以下结果:

{'line 1': {'line 2': {'line 3': {}}}, 'line 4': {}, 'line 5': {}}

或者稍微复杂一点:

tuple_list = [(1, 'line 1'), (2, 'line 2'), (2, 'line 6'), (3, 'line 3'), (3, 'line 7'), (1, 'line 4'), (1, 'line 5')]

会产生

{'line 1': {'line 2': {}, 'line 6': {'line 3': {}, 'line 7': {}}}, 'line 4': {}, 'line 5': {}}

由于您的等级不限于少数,通过普通的IF 来做这件事并不是一个好方法。最好构造一个树,然后遍历树并创建所需的表示。这样做也很容易,你有几个根节点(其中parent = None),每个节点都有一个子列表,这对子节点重复,所以你有一棵树。您现在从根开始并进行所需的订购!

它很容易实现,我想你明白了!