Python代码列出依赖项,避免循环
假设您有一个描述项目依赖关系的字典,大致如下:Python代码列出依赖项,避免循环,python,recursion,functional-programming,Python,Recursion,Functional Programming,假设您有一个描述项目依赖关系的字典,大致如下: deps = { 'A': ['B', 'C', 'D'], 'B': ['C', 'E'], 'C': ['D', 'F'], 'D': ['C', 'G'], 'E': ['A'], 'H': ['N'], } 这意味着项目“A”依赖于项目“B”、“C”和“D”等。显然,这可能具有任意复杂性 如何编写一个函数get_all_deps(item),该函数提供item的所有依赖项的列表,没有重复项,
deps = {
'A': ['B', 'C', 'D'],
'B': ['C', 'E'],
'C': ['D', 'F'],
'D': ['C', 'G'],
'E': ['A'],
'H': ['N'],
}
这意味着项目“A”依赖于项目“B”、“C”和“D”等。显然,这可能具有任意复杂性
如何编写一个函数get_all_deps(item)
,该函数提供item
的所有依赖项的列表,没有重复项,也没有item
。例如:
> get_all_deps('H')
['N']
> get_all_deps('A')
['B', 'C', 'D', 'E', 'F', 'G']
> get_all_deps('E')
['A', 'B', 'C', 'D', 'F', 'G']
我在寻找简洁的代码——理想情况下是一个递归函数。性能对于我的用例并不十分重要-我们讨论的是相当小的依赖关系图(例如几十个项)您可以使用堆栈/待办事项列表来避免递归实现:
deps = {
'A': ['B', 'C', 'D'],
'B': ['C', 'E'],
'C': ['D', 'F'],
'D': ['C', 'G'],
'E': ['A'],
'H': ['N'],
}
def get_all_deps(item):
todo = set(deps[item])
rval = set()
while todo:
subitem = todo.pop()
if subitem != item: # don't add start item to the list
rval.add(subitem)
to_add = set(deps.get(subitem,[]))
todo.update(to_add.difference(rval))
return sorted(rval)
print(get_all_deps('A'))
print(get_all_deps('E'))
print(get_all_deps('H'))
结果:
['B', 'C', 'D', 'E', 'F', 'G']
['A', 'B', 'C', 'D', 'F', 'G']
['N']
todo
集合包含要处理的元素
- 弹出一个元素并将其放入返回值列表中
- 循环直到没有更多元素(好的,这里有一个循环)
- 如果元素不在返回值中,则只添加要处理的元素
- 返回排序列表
set
差异避免了循环依赖的问题,并且避免了“最大递归深度”。唯一的限制是系统内存。哦,就像依赖项的传递闭包一样?你知道你的例子中存在依赖循环吗?@depperm我已经做了几次尝试,并且有不止一个有效的解决方案-所有这些都像黑客一样。我最后使用的方法只是对递归深度设置了一个任意的人工限制。一定有更好的解决方案。这是一个图形搜索问题。你有一个循环图。再次强调,研究广度优先搜索。你也可以看看Dijkstra的算法来了解避免循环的一个经典例子:你必须跟踪你访问过的节点。@JordanDimov问题不是人们没有阅读你的问题,问题是你有一个期望(相当标准)来显示你的尝试和你被卡住的地方。选择你的“最简单的”解决方案,并准确地解释你认为哪些不适合你的目的。您已经说过性能并不重要,因此,制定一个与之相关的简洁性基准实际上是您问题的关键部分。太好了,谢谢。我尝试了一个递归变量(例如,传递一个“seen”集合来记录递归),但没有成功。。堆叠技巧很棒。我仍然在想,是否有一种聪明的方法可以递归地实现这一点。