python:从零散的字典组装成树状嵌套字典

最近工作接触到图数据库,图和树的存储形式是一对对基本的指向关系。
当需要访问时,不需要知道整体结构,只需要知道子节点,就可以把图结构表示出来了。

出于好奇,这里将这些基本的指向关系组成一个完整的结构。

首先,我们把问题简化,python中最基本的表示关系的数据结构是字典,
假设有这样一组关系,我们把它们用字典表示:

dict_list = [{
    
    'a': "b"},
             {
    
    'a': "c"},
             {
    
    'a': "d"},
             {
    
    'b': "e"},
             {
    
    'a': "f"},
             {
    
    'd': "g"},
             {
    
    'd': "h"},
             {
    
    'e': "i"}]

组成树的过程分成三步:
1.找根节点
2.找出所有节点的子节点
3.深度优先遍历(或广度优先遍历)组装成最终的树
说明:不能用这种方式生成前缀树(Trie), 因为在前缀树中,相同字母是可以重复出现在不同位置的,而在这里一个字母只能出现在一个地方,在知识图谱中比较适用。

找根节点

我们先把根节点找出来,找根的依据是它没有在值中出现过,只能出现在键里:

# 首先,找根节点的方法
possible_root = set()
impossible_root = set()
for d in dict_list:
    possible_root |= d.keys()  # 根节点只能在键里
    impossible_root |= set(d.values())  # 值一定不是根节点

# 既是键又不是值,只能是根,由于只有一个根,剩下的就只有一个根节点
root_set = possible_root - impossible_root
# 既是值又没有作为键出现过,说明没有节点在它之后,就是叶子节点
leaf_set = impossible_root - possible_root

看看结果:

print("root_set: ", root_set)
print("leaf_set: ", leaf_set)

成功找到根a:
在这里插入图片描述

找出所有节点的子节点

由于我们目标是组装成完整的树,因此要把各节点的所有子节点都找出来:

group = {
    
    }
for d in dict_list:
    for k, v in d.items():
        group.setdefault(k, [])
        group[k].append(v)
print(group)

结果:
在这里插入图片描述

深度优先遍历组装成最终的树

有了group这个信息,就可以把完整的嵌套字典拼出来了:

def dfs(temp, sub_tree):
    for r in temp:
        children = group.get(r)
        if children is None:
            return
        sub_tree[r] = {
    
    }
        for child in children:
            sub_tree[r][child] = {
    
    }
            dfs({
    
    child}, sub_tree[r])


result = {
    
    }
# 从root开始
dfs(root_set, sub_tree=result)
print(result)

结果:
在这里插入图片描述

完整代码

完整代码:

from pprint import pprint


dict_list = [{
    
    'a': "b"},
             {
    
    'a': "c"},
             {
    
    'a': "d"},
             {
    
    'b': "e"},
             {
    
    'a': "f"},
             {
    
    'd': "g"},
             {
    
    'd': "h"},
             {
    
    'e': "i"}]

# 首先,找根节点的方法
possible_root = set()
impossible_root = set()
for d in dict_list:
    possible_root |= d.keys()  # 根节点只能在键里
    impossible_root |= set(d.values())  # 值一定不是根节点

# 既是键又不是值,只能是根,由于只有一个根,剩下的就只有一个根节点
root_set = possible_root - impossible_root
# 既是值又没有作为键出现过,说明没有节点在它之后,就是叶子节点
leaf_set = impossible_root - possible_root
print("root_set: ", root_set)
print("leaf_set: ", leaf_set)

group = {
    
    }
for d in dict_list:
    for k, v in d.items():
        group.setdefault(k, [])
        group[k].append(v)

pprint(group)


def dfs(temp, sub_tree):
    for r in temp:
        children = group.get(r)
        if children is None:
            return
        sub_tree[r] = {
    
    }
        for child in children:
            sub_tree[r][child] = {
    
    }
            dfs({
    
    child}, sub_tree[r])


result = {
    
    }
# 从root开始
dfs(root_set, sub_tree=result)
pprint(result)

猜你喜欢

转载自blog.csdn.net/qq_17065591/article/details/107528137