使用递归从大型dict构建子字典

时间:2017-05-30 23:02:32

标签: python dictionary

我有一本字典,链接父母 - 女儿衰变链中的各种物种。例如:

d = {
    'A':{'daughter':['B']},
    'B':{'daughter':['C']},
    'C':{'daughter':['D']},
    'D':{'daughter':['None']},
    'E':{'daughter':['F']},
    'F':{'daughter':['G']},
    'G':{'daughter':['H']},
    'H':{'daughter':[None]}
}

在这个词典中,顶级键是'父'和'子'(即父级在链中衰减的内容)被定义为键值:附加到父键的字典中的值项。当为女儿提供None时,这被认为是链的末端。

我希望函数根据起始父级的用户输入返回包含链中项目的子字典。我还想知道链中每个项目的位置。在子词典中,这可以是第二个字段('position')。

例如,如果用户想要在'A'处启动链,我希望函数返回:

{'A':{'position':1, 'daughter':['B']},
 'B':{'position':2, 'daughter':['C']},
 'C':{'position':3, 'daughter':['D']},
 'D':{'position':4, 'daughter':['None']}}

同样,如果起始值为'E',我希望它返回:

{'F':{'position':1, 'daughter':['G']},
 'G':{'position':3, 'daughter':['H']},
 'H':{'position':4, 'daughter':['None']}}

当链接是一对一时,即一个项目衰变为另一个项目,进入另一个项目等,这相对容易。

如果我现在使用一个更复杂的例子,如下所示,您可以看到'B'实际上已经衰变为'C'和'D',并且从那时开始,链是分开的。

A => B => C => E => G和A => B => D => F => ħ

d = {
    'A':{'daughter':['B']},
    'B':{'daughter':['C', 'D']},
    'C':{'daughter':['E']},
    'D':{'daughter':['F']},
    'E':{'daughter':['G']},
    'F':{'daughter':['H']},
    'G':{'daughter':[None]},
    'H':{'daughter':[None]}
}

在这种情况下,我想要一个函数来返回以下输出。你会注意到由于两条链的转移,位置值接近于平衡线的水平,例如C = 3且D = 4,但不完全相同。我不想一直关注C链,然后重复D链。

{'A':{'position':1, 'daughter':['B']},
 'B':{'position':2, 'daughter':['C']},
 'C':{'position':3, 'daughter':['E']},
 'D':{'position':4, 'daughter':['F']}
 'E':{'position':5, 'daughter':['G']}
 'F':{'position':6, 'daughter':['H']}
 'G':{'position':8, 'daughter':['None']}
 'H':{'position':9, 'daughter':['None']}
}

有什么想法?该功能应该能够应对链中的多个转移。

标记

1 个答案:

答案 0 :(得分:0)

如果你不想从C一路向下走,那么breadth-first search可能会有所帮助。

def bfs(d, start):
    answer = {}
    queue = [start]
    head = 0

    while head < len(queue):
        # Fetch the first element from queue
        now = queue[head]
        answer[now] = {
            'position': head+1,
            'daughter': d[now]['daughter']
        }

        # Add daughters to the queue
        for nxt in d[now]['daughter']:
            if nxt == None:
                continue
            queue.append(nxt)

        head += 1

    return answer

d = {
    'A': {'daughter': ['B']},
    'B': {'daughter': ['C', 'D']},
    'C': {'daughter': ['E']},
    'D': {'daughter': ['F']},
    'E': {'daughter': ['G']},
    'F': {'daughter': ['H']},
    'G': {'daughter': [None]},
    'H': {'daughter': [None]}
}

print(bfs(d, 'A'))