使用for循环从列表中删除元素不起作用,但是使用列表理解是可以的

时间:2019-07-07 13:14:53

标签: python list list-comprehension

好的,这个问题实际上已经解决了,但是我仍然想知道为什么。我正在尝试从二维数组中删除元素,这是代码:

print("adj in the while loop: ", adj)
for z in adj:
    print("for loop: ", z)
    if z[-1] is True:
        adj.remove(z)
result += 1
print("adj after all execution: ", adj)

控制台输出:

adj in the while loop: [[1, True], [0, 2, True], [1, True]]
for loop: [1, True]
for loop: [1, True]
adj after all execution: [[0, 2, True]]

这不符合预期。执行后正确的输出应为[]

因此,我开始使用列表理解来编辑代码。

列表理解代码:

adj = [z for z in adj if z[-1] is not True]

它按预期工作。输出为[]

这使我感到困惑。为什么这两种看似相同的方法会产生不同的结果?有人可以向我解释吗?

3 个答案:

答案 0 :(得分:4)

这两种方法不相同。在列表理解中,您永远不会调用adj.remove(z)

列表理解是在迭代adj时创建一个新列表,然后在完成后将(空)列表分配回adj。迭代期间,adj不会改变,val selectedItem = MediatorLiveData<Voyage>() var voyages: LiveData<Resource<List<Voyage>>> var voyageFilter = MutableLiveData<VoyageFilter>() selectedItem.addSource(voyageFilter) { filter -> //do something } selectedItem.addSource(voyages) { listResource -> //do something } 只是在最后一次迭代之后。

答案 1 :(得分:2)

您绝对可以使用.remove(),但要遍历原始副本而不是原始副本本身:

adj = [[1, True], [0, 2, True], [1, True]]

for z in adj[:]:
    print("for loop: ", z)
    if z[-1] is True:
        adj.remove(z)
result += 1
print("adj after all execution: ", adj)

它将打印出一个空列表。

在这里,我们遍历副本,但从原始副本中删除元素。这样可以避免您的代码出现差异。

答案 2 :(得分:1)

如果在元素上使用方法listremove,则在append上并与其内部块同时进行迭代是不正确的方法。基本上最好将编码更改为其他方式。就像奥斯汀在他的代码中建议的那样,或者使用单独的索引而不是迭代索引或元素。

那是

adj = [[3, 4, 5, False], [8, 7, False], [0, True], [-1, False], [1, True], [0, 2, False], [0, 2, True], [1, True], [4, False]]

del_index = 0
for i in range(len(adj)):
    print("for loop: ", adj[del_index])
    if adj[del_index][-1] is True:
        adj.remove(adj[del_index])
    else:
        del_index+=1
print("adj after all execution: ", adj)

过滤器可用于此目的

filter(lambda elem: elem[-1] is True, adj)

这可能会导致系统崩溃,因为将append元素添加到列表并同时在同一元素上进行迭代。

crash_my_system = [0]
for i in crash_my_system: crash_my_system.append(i+1)

不仅对List如此。这对于所有可变数据结构(例如Dict)都是通用的。请参阅:Christoph Zwerschke's blog