Python中使用remove函数的注意事项

使用列表的remove函数时的注意事项

前几天写寻找最稠密子图问题的算法时,在测试的时候发现了一个bug,那就是删除度数最低的顶点时,也要把有关的边都删除,但是当删除的边在列表中相邻时,只会删除第一条边,最后查找资料,发现还是对python遍历列表的方式没理解透彻

这里是出现bug部分的代码

1
2
3
4
5
def delMinNode(minNode): # 删除度数最小的节点,相应的边也会被删除
nodes.remove(minNode)
for edge in edges:
if minNode in edge:
edges.remove(edge)

再看下面的一个例子

1
2
3
4
5
a = [1, 2, 3, 4, 5, 5, 6, 7]
for i in a:
if i == 5:
a.remove(i)
print(a)

这段代码的目的是将列表中所有的5都删除,然后将列表打印出来, 但是运行结果却是

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

下面来分析原因:

首先了解下python当中的遍历机制,python中遍历是按照下标来遍历的,即a[0],a[1], a[2]….. 一个个遍历过去

再看上面的例子,第一个5是在a[4]的位置,当遍历进行到a[4]时,这个5被删除,这个时候后面的每个元素都要往前进一位,第二个5到了a[4]的位置,6变成a[5]…..于是下一次循环时,会去判断a[5],也就是6,第二个5遍历时被跳过,没被删除,导致了这样的运行结果

于是之前的算法中代码可以这样修改

1
2
3
4
5
6
def delMinNode(minNode): # 删除度数最小的节点,相应的边也会被删除
nodes.remove(minNode)
newEdges = copy.deepcopy(edges)
for edge in newEdges:
if minNode in edge:
edges.remove(edge)

深复制一个与原列表相同的新列表,然后遍历这个新列表,删除时是删原列表中的边,便可避免相邻边无法删除的bug