我正在实现dijkstras算法来计算最短路径。我的问题是,是否有更简洁的方法来实现以下理解(即没有if [b for a,b in G[x] if a not in X]!=[]]
加到最后)。
在下文中,G是一个图表,其中的键是图形节点,每个节点都有一个表示其连接边缘的元组列表。因此每个元组包含以下信息:(连接节点,到连接节点的距离)。 X是算法已经查看过的一组节点,A是将已经找到的节点映射到起始节点的最短距离,在这种情况下是节点1.
更新:抱歉,我举了一个有效的例子,如果删除了理解的最后部分,这里就不起作用。
G = {1: [(2, 20), (3, 50)], 2: [(3, 10), (1, 32)], 3: [(2, 30), (4, 10)], 4: [(1, 60)]}
X = {1,2,3}
A = {1: 0, 2: 20, 3:30}
mindist = min([A[x] + min([b for a,b in G[x] if a not in X]) for x in X if [b for a,b in G[x] if a not in X]!=[]])
问题是如何将思维导师写成可以处理min([[],[some number],[])
的理解。
最后一部分,
if [b for a,b in G[x] if a not in X]!=[]]
只是删除空列表,所以min不会失败,但是有更好的方法来编写它
理解所以没有空列表。
答案 0 :(得分:2)
这是一个想法:
minval = [float('+inf')]
min(A[x] + min([b for a, b in G[x] if a not in X] + minval) for x in X)
=> 40
诀窍?确保最里面的min()
总是有一个值可以使用,即使它是一个虚拟的:一个正的无限,因为任何东西都会比它小。通过这种方式,最外面的min()
将在计算最小值时忽略inf
值(对应于空列表)。
答案 1 :(得分:1)
首先,空列表在布尔值中被视为false,因此您无需针对[]
测试不等式; if [b for a,b in G[x] if a not in X]
就足够了。
你真正想做的是生成内部列表一次,然后一次性测试和计算最小值。使用额外的内部'循环'来做到这一点:
mindist = min(A[x] + min(inner)
for x in X
for inner in ([b for a,b in G[x] if a not in X],) if inner)
for inner over (...,)
循环迭代生成列表一次的单元素元组,以便在计算之前可以测试它是否为空(if inner
)将A[x] + min(inner)
结果传递给外部 min()
来电。
请注意,您不需要该外循环的列表推导;这是一个生成器表达式,可以节省您构建列表对象,然后再次将其丢弃。
演示:
>>> G = {1: [(2, 20), (3, 50)], 2: [(3, 10), (1, 32)], 3: [(2, 30), (4, 10)], 4: [(1, 60)]}
>>> X = {1,2,3}
>>> A = {1: 0, 2: 20, 3:30}
>>> min(A[x] + min(inner)
... for x in X
... for inner in ([b for a,b in G[x] if a not in X],) if inner)
40
答案 2 :(得分:1)
好的,我必须解开那个坚果列表理解来弄清楚你在说什么 - 我认为这是大致相同的代码:
dists = []
for x in X:
newdists = [b for a,b in G[x] if a not in X]
if len(newdists) > 0
dists.append(A[x] + min(newdists))
mindist = min(dists)
这是一种消除相关测试的方法:
import sys
def newMin(values):
if len(values) == 0:
return float('inf')
else:
return min(values)
mindist = min(A[x] + newMin([b for a,b in G[x] if a not in X]) for x in X)
print mindist
输出:
40
答案 3 :(得分:0)
这不是一个完整的解决方案,但由于你刚刚摆脱空列表,你可以缩短条件。空列表被评估为False。包含任何内容的列表将被评估为true。只需提供列表作为条件。对于所有空的内置数据类型都是如此。