在嵌套列表python中查找插入的所有可能组合

时间:2020-04-05 10:08:11

标签: python

对于车辆路线问题,我需要检查具有多条路线的特定列表,插入某个城市会对该路线列表的总长度产生影响。所有城市都用整数表示。

基本上,我需要在每个可能的“位置”中插入一个整数元素,然后继续计算所有可能性中最短的距离。考虑以下嵌套的路由列表:

rl = [[0, 7, 40, 41, 96, 34, 75, 127, 48, 65, 79, 27, 126, 78, 0],
[0, 56, 45, 2, 67, 66, 59, 124, 82, 133, 102, 54, 57, 0],
[0, 35, 97, 81, 87, 80, 61, 98, 101, 52, 83, 60, 109, 39, 53, 0]] 

这里0是总部,这是每天路线的起点和终点。假设我需要插入以9表示的城市。

预期的输出将是:

[[0, 9, 7, 40, 41, 96, 34, 75, 127, 48, 65, 79, 27, 126, 78, 0], ...rest of list] 
[[0, 7, 9, 40, 41, 96, 34, 75, 127, 48, 65, 79, 27, 126, 78, 0], ...rest of list] 
[[0, 7, 40, 9  41, 96, 34, 75, 127, 48, 65, 79, 27, 126, 78, 0], ...rest of list] 
[[0, 7, 40, 41, 9  96, 34, 75, 127, 48, 65, 79, 27, 126, 78, 0], ...rest of list]

,依此类推,直到尝试了所有可能的位置并将其附加到可行性矩阵之后。

我编写了以下函数来实现这一目的:

def check_possible_insertions(city, route_list):
    feasible_matrix = []
    for i, route in enumerate(route_list):
        for j, value in enumerate(route[1:]):
            possibility = route_list.copy()
            possibility[i].insert(j+1, city)
            feasible_matrix.append(possibility)
    return feasible_matrix

在这里我首先创建一个“可行的”矩阵,然后遍历所有路线。然后,对于路线中的每个可能位置(第二个for循环),我创建一个route_list的副本(作为参数传递的原始路线列表)。然后,在正确的路线[i]的正确位置(j)插入城市,并将可能性添加到我的可行性矩阵中。

至少,这就是我认为这段代码应该起作用的方式。函数调用check_possible_insertions(9, rl)告诉我代码的行为与预期不同:它只是在每条路由的前面插入#j个9的数字。我正在忽略某些东西,但无法弄清楚是什么。 我在做什么错了?

2 个答案:

答案 0 :(得分:2)

您只是浅表复制整个列表。您打算浅复制一条单独的路线:

possibility = route.copy()
possibility.insert(j, city)

内循环value中也未使用,因此该功能的可能版本为:

def check_possible_insertions(city, route_list):
    feasible_matrix = []
    for i, route in enumerate(route_list):
        new_list=[]
        feasible_matrix.append(new_list)
        for j in range(1, len(route)):
            possibility = route.copy()
            possibility.insert(j, city)
            new_list.append(possibility)
    return feasible_matrix

这将生成路由列表,找到最佳路由后,可以将其简化为新的rl。 例如:

rl = [[0, 7, 40, 78, 0],
[0, 56, 45, 2, 0],
[0, 35, 97, 60, 0]]

result = check_possible_insertions(9,rl)
print(result)

输出:

[[[0, 9, 7, 40, 78, 0], [0, 7, 9, 40, 78, 0], [0, 7, 40, 9, 78, 0], [0, 7, 40, 78, 9, 0]], [[0, 9, 56, 45, 2, 0], [0, 56, 9, 45, 2, 0], [0, 56, 45, 9, 2, 0], [0, 56, 45, 2, 9, 0]], [[0, 9, 35, 97, 60, 0], [0, 35, 9, 97, 60, 0], [0, 35, 97, 9, 60, 0], [0, 35, 97, 60, 9, 0]]]

答案 1 :(得分:1)

问题是route_list.copy()创建了一个浅表副本,内部列表是相同的对象,例如:

rl = [[0, 7, 40, 41, 96, 34, 75, 127, 48, 65, 79, 27, 126, 78, 0],
[0, 56, 45, 2, 67, 66, 59, 124, 82, 133, 102, 54, 57, 0],
[0, 35, 97, 81, 87, 80, 61, 98, 101, 52, 83, 60, 109, 39, 53, 0]]

cp = rl.copy()
cp[0].insert(0, 9)

for i in rl:
print(i)

输出

[9, 0, 7, 40, 41, 96, 34, 75, 127, 48, 65, 79, 27, 126, 78, 0]
[0, 56, 45, 2, 67, 66, 59, 124, 82, 133, 102, 54, 57, 0]
[0, 35, 97, 81, 87, 80, 61, 98, 101, 52, 83, 60, 109, 39, 53, 0]

您可以看到rl的第一个列表已被修改,因为它与cp中的第一个列表相同。

作为解决方案,您可以使用Deepcopy

import copy


def check_possible_insertions(city, route_list):
    feasible_matrix = []
    for i, route in enumerate(route_list):
        for j, value in enumerate(route[1:]):
            possibility = copy.deepcopy(route_list)
            possibility[i].insert(j+1, city)
            feasible_matrix.append(possibility)
    return feasible_matrix

输出 (前5个结果)

[[0, 9, 7, 40, 41, 96, 34, 75, 127, 48, 65, 79, 27, 126, 78, 0], [0, 56, 45, 2, 67, 66, 59, 124, 82, 133, 102, 54, 57, 0], [0, 35, 97, 81, 87, 80, 61, 98, 101, 52, 83, 60, 109, 39, 53, 0]]
[[0, 7, 9, 40, 41, 96, 34, 75, 127, 48, 65, 79, 27, 126, 78, 0], [0, 56, 45, 2, 67, 66, 59, 124, 82, 133, 102, 54, 57, 0], [0, 35, 97, 81, 87, 80, 61, 98, 101, 52, 83, 60, 109, 39, 53, 0]]
[[0, 7, 40, 9, 41, 96, 34, 75, 127, 48, 65, 79, 27, 126, 78, 0], [0, 56, 45, 2, 67, 66, 59, 124, 82, 133, 102, 54, 57, 0], [0, 35, 97, 81, 87, 80, 61, 98, 101, 52, 83, 60, 109, 39, 53, 0]]
[[0, 7, 40, 41, 9, 96, 34, 75, 127, 48, 65, 79, 27, 126, 78, 0], [0, 56, 45, 2, 67, 66, 59, 124, 82, 133, 102, 54, 57, 0], [0, 35, 97, 81, 87, 80, 61, 98, 101, 52, 83, 60, 109, 39, 53, 0]]
[[0, 7, 40, 41, 96, 9, 34, 75, 127, 48, 65, 79, 27, 126, 78, 0], [0, 56, 45, 2, 67, 66, 59, 124, 82, 133, 102, 54, 57, 0], [0, 35, 97, 81, 87, 80, 61, 98, 101, 52, 83, 60, 109, 39, 53, 0]]