在我下面的代码中,for 循环传递的值不在正在迭代的列表中。 我正在编写一个简单的寻路函数,其中传递起点和终点,输出是从起点到终点的路径。名为 connection 的字典具有地图上所有点的键,其值是它连接到的所有其他点的列表。您只能通过节点从一个点到达另一个点(认为节点就像道路,字母是房子)。
在这种情况下,我输入了一个起点'A'和一个终点F。预期的输出是:
['A', 'NODE1', 'NODE2', 'NODE4', 'F']
然而,我得到的输出是:
['A', 'NODE1', 'NODE2', 'NODE3', 'NODE4', 'F']
经过一些故障排除后,我发现了一个非常奇怪的问题。在下面的print语句中,最后一次打印如下:
NODE3 ['NODE2', 'C', 'D'] NODE4
打印的格式是:"key, dictionary[key], item inside dictionary[key]" 但是,'item'实际上不在打印的列表中!
我没有改变我正在迭代的键:值对,所以我不知道为什么我会遇到这个问题。我几乎从不在我的函数中使用递归,所以也许这就是问题的来源......有人知道发生了什么吗?
connections = {'A':['NODE1'],
'B':['NODE1'],
'NODE1':['A', 'B', 'NODE2'],
'NODE2':['NODE1', 'NODE3', 'NODE4'],
'NODE3':['NODE2', 'C', 'D'],
'NODE4':['NODE2', 'E', 'F'],
'C':['NODE3'],
'D':['NODE3'],
'E':['NODE4'],
'F':['NODE4']}
def find_path(start_nodes, end):
nodes = []
for start in start_nodes:
if end in connections[start[-1]]:
s = start
s.append(end)
return s
else:
for item in connections[start[-1]]:
print(start[-1], connections[start[-1]], item)
if 'NODE' in item and item not in start:
s = start
s.append(item)
nodes.append(s)
find_path(nodes, end)
s = find_path([['A']], 'F')
进一步的代码解释: find_path 接受一个起点列表和一个终点。然后它检查字典以查看连接到起点的内容。如果端点已连接,则返回路径。否则,它会检查连接的节点。一旦找到所有连接的节点,该函数将重新启动,并存储到最近节点的路径,连接的节点现在是起点。直到找到终点为止。
答案 0 :(得分:1)
Barmar 首先找到了它,但我会拼写出来(我第一次通过自己错过了他的意思)。在函数末尾更改此语句:
find_path(nodes, end)
# print(find_path([['A']], 'F'))
# None
到
return find_path(nodes, end)
# print(find_path([['A']], 'F'))
# ['A', 'NODE1', 'NODE2', 'NODE3', 'NODE4', 'F']
按照您的方式,您尝试返回的列表不会超过最内层。这样你就可以将它传递到表面。
答案 1 :(得分:1)
我相信发生的事情是通过放置 s = start
,您最终也会修改变量 start
。这就是为什么意外的 NODE3
会成为最终答案的原因
这是因为当你给一个新变量赋值时,它只存储引用号,修改一个变量会修改另一个。
例如
list_values = [1, 2, 3, 4, 5]
new_list = list_values
new_list.append("Interesting")
print("list_values: ", list_values)
print("new_list: ", new_list)
输出:
list_values: [1, 2, 3, 4, 5, 'Interesting']
new_list: [1, 2, 3, 4, 5, 'Interesting']
这对于小列表来说是有意义的,但是当您考虑到列表可以包含大量值时,使用参考号会更快
因此,解决方案是我们实际上需要将整个列表复制到“s”,而不仅仅是引用编号。
为此:
import copy
s = copy.deepcopy(start) # use this instead of s = start
最终代码:
connections = {'A':['NODE1'],
'B':['NODE1'],
'NODE1':['A', 'B', 'NODE2'],
'NODE2':['NODE1', 'NODE3', 'NODE4'],
'NODE3':['NODE2', 'C', 'D'],
'NODE4':['NODE2', 'E', 'F'],
'C':['NODE3'],
'D':['NODE3'],
'E':['NODE4'],
'F':['NODE4']}
import copy
def find_path(start_nodes, end):
global s
nodes = []
for start in start_nodes:
if end in connections[start[-1]]:
s = copy.deepcopy(start)
s.append(end)
return s
else:
for item in connections[start[-1]]:
if 'NODE' in item and item not in start:
s = copy.deepcopy(start)
s.append(item)
nodes.append(s)
find_path(nodes, end)
find_path([['A']], 'F')
print(s)
输出:['A', 'NODE1', 'NODE2', 'NODE4', 'F']
编辑: 看起来我发布这个答案已经晚了,@Jamie Deith 和 @Barmar 已经回答了。无论如何,我已经提到了为什么它没有按预期工作,所以这仍然会有所帮助。