我有一个“非标准”形式的字典树,如下所示:
tree = {'0': {'A': {'B': {'C': {}}}},
{'D': {'E': {}},
{'F': {}}}}
叶子节点被定义为字典键值对,其中值是空字典。 我想提取所有叶到根路径作为列表列表,如下所示:
paths_ = [['C', 'B', 'A', '0'],
['E', 'D', '0'],
['F', 'D', '0']]
如果有用,路径也可以反转。
paths_ = [['0', 'A', 'B', 'C'],
['0', 'D', 'E'],
['0', 'D', 'F']]
我知道我必须递归地执行此操作,并且每个路径都需要一个累加器列表。如果函数产生路径列表也会很好。到目前为止我所拥有的是:
def paths(node, subtree, acc=[]):
if not subtree:
yield [node]+acc
for n, s in subtree.items():
yield paths(n, s, acc)
它并没有真正做我想要的事情:
paths_ = list(paths('0', tree['0']))
理想情况下,这应该返回列表列表。任何帮助将不胜感激。
答案 0 :(得分:7)
假设您确实想要tree
的以下结构:
tree = {'0': {'A': {'B': {'C': {}}},
'D': {'E': {},
'F': {}}}}
这是一个类似的paths()
函数,可以执行您想要的操作:
def paths(tree, cur=()):
if not tree:
yield cur
else:
for n, s in tree.items():
for path in paths(s, cur+(n,)):
yield path
结果:
>>> list(paths(tree))
[('0', 'A', 'B', 'C'), ('0', 'D', 'E'), ('0', 'D', 'F')]
请注意,我使用元组作为默认参数而不是列表,这是因为mutable default arguments can get you into trouble。
答案 1 :(得分:1)
您可以使用类似于所选答案的内容。
import collections
def iter_paths(tree, parent_path=()):
for path, node in tree.iteritems():
current_path = parent_path + (path,)
if isinstance(node, collections.Mapping):
for inner_path in iter_paths(node, current_path):
yield inner_path
else:
yield current_path
对于以下词典:
tree = {'A':1,
'B':{'B1':1, 'B2':2},
'C':{'C1':{'C11':1, 'C12':2},'C2':{'C21':1, 'C22':2}}}
输出应该是(收益率顺序可能不同):
('A',)
('C', 'C2', 'C22')
('C', 'C2', 'C21')
('C', 'C1', 'C12')
('C', 'C1', 'C11')
('B', 'B1')
('B', 'B2')
答案 2 :(得分:0)
假设树结构具有以下格式: {'0':{'A':{},'B':{}}} 那么这样的事情应该可以解决问题。
def paths(nodeId, children, ancestors, allPaths):
ancestors.append(nodeId)
if len(children) == 0:
allPaths.append(ancestors)
else:
for childId in children:
paths(childId, children[childId], ancestors[:], allPaths)
allPaths = []
paths('0', tree['0'], [], allPaths)
这样的事情应该有用。通常我会先试试这个,但我现在正在我的iPad上。如果它不起作用,它应该给你一些想法。