【问题标题】:Shortest path between list of list列表列表之间的最短路径
【发布时间】:2019-09-27 17:28:37
【问题描述】:

假设我有一个这样的列表:

[
[1, [2, 3]],
[2, [4, 5]],
[4, [6, 7]],
[3, [7]]
]

我想编写能找到从17 的最短路径的代码,在这种情况下,就是1 -> 3 -> 7

这是我目前所拥有的:

start = 1
lst = [[1, [2, 3]], [2, [4, 5]], [4, [6, 7]], [3, [7]]]

def getIt(start):
    for nest in lst:
        if start == lst[0]:
            return(nest[1])

allLists = []
loopCleaner = []
def travel(paths, totalList):
    if paths is not None:
        if 7 in paths:
            allLists.append(totalList)
        else:
            for path in paths:
                if path not in loopCleaner:
                    loopCleaner.append(path)
                    totalList.append(path)
                    travel(getIt(path), totalList)

print(travel(lst, []))

我正在尝试混合使用递归和循环,但它要么输出太长的路径,要么只输出无。

我的逻辑:通过getIt获取所有可能的嵌套列表。

然后通过递归遍历它们,并在它下降时继续添加到总列表,直到在其中一个路径中找到 7。在这种情况下,我们结束并退出。我如何以这样的方式编码,我只需得到[1, 3, 7]

【问题讨论】:

  • 该列表看起来像一个邻接矩阵。你研究过 Djikstras 算法的最短路径吗?
  • NetworkX 模块实现了shortest_path() 函数,如@rdas 所述,如果您设法将其转换为邻接矩阵或图形,您应该很容易找到最短的路径
  • 我没试过,我怎么把它变成邻接矩阵还是已经?

标签: python loops recursion


【解决方案1】:

您可以将递归与生成器一起使用:

def paths(d, start, end, c = [], seen=[]):
  if end in d.get(start, []):
     yield c+[end]
  else:
     for i in filter(lambda x:x not in seen, d.get(start, [])):
        yield from paths(d, i, end, c = c+[i], seen=seen+[i])

data = [[1, [2, 3]], [2, [4, 5]], [4, [6, 7]], [3, [7]]]
print(min(list(paths(dict(data), 1, 7, c=[1])), key=len))

输出:

[1, 3, 7]

【讨论】:

  • 在我的完整数据集上尝试它时,我得到maximum recursion depth exceeded while calling a Python object 但对于最低限度的可行,它工作得很好。肯定有循环,所以我会调查一下。
  • @AndrewRaleigh 如果可能的话,您能否发布更大的数据集样本以及一些所需的开始和结束值?
  • 试过你的新功能,它有效!这比我想象的要容易得多。你能解释一下它是如何工作的吗?
  • @AndrewRaleigh 没问题。上面的代码将原始列表转换为字典,以便更清晰、更有效地查找键,然后遍历存储在每个子列表中的子值。如果在子列表中找到end 值,则生成键的运行列表。在每次paths 调用中,被迭代的子值被添加到seen 列表中,以确保函数可以忽略循环并防止无限递归错误。
猜你喜欢
  • 2015-05-17
  • 2019-04-10
  • 2013-04-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多