首页 > 解决方案 > Python 在迭代列表时不会从列表中删除所有项目

问题描述

我有一本字典和一个列表,如下所示

correction =  {u'drug.ind': u'Necrosis', "date": "exp"}
drugs =  [[u'drug.aus', u'Necrosis'], [u'drug.nz', u'Necrosis'], [u'drug.uk', u'Necrosis'], [u'drug.ind', u'Necrosis'], [u'cheapest', u'drug.ind'], [u'date', u'']]

现在基本上我查看更正字典值,每当它匹配列表中drugs列表的每个第二个元素时,我都会删除它们。

这就是我所做的

if correction and drugs:
    for i,x in correction.items():
        for j,k in enumerate(drugs):
            if len(i.split(".")) > 1:  # need to do the operation only for drugs which is always given in this format
                if x == k[1]:
                    drugs.pop(j)

理想情况下,drugs列表现在应该看起来像

drugs = [['cheapest', 'drug.ind'], ['date', '']]

但由于某种原因,它看起来像

[['drug.nz', 'Necrosis'], ['drug.ind', 'Necrosis'], ['cheapest', 'drug.ind'], ['date', '']]

我希望所有看起来像坏死的东西都会被移除。但它也可以将其删除。

为什么我会遇到这种行为?我究竟做错了什么?

标签: pythonlist

解决方案


您正在迭代列表 ( drugs),并且在循环内部,您正在从同一个列表中删除元素。

for在可迭代对象上执行循环时,Python 会不断增加一个内部“索引”变量,该变量有助于 Python 跟踪列表中的当前项。

在循环中,假设您删除了 index = 3 处的项目。现在,列表的其余部分(您尚未迭代的项目)将移动一个位置。先前存在于索引 4 的项目现在将出现在被删除的项目腾出的索引 3 处。为了在下一次迭代中处理这个移位的项目,内部“索引”变量也必须再次为下一次迭代取值 3。但是 Python 将索引变量从 3 增加到 4 以进行下一次迭代,就像它通常从一个迭代到另一个迭代一样。结果是被删除项目之后的项目不会被你的 for 循环的主体检查/处理(因为索引是 4 而不是 3),因此即使它符合删除标准也不会被删除.

几种解决方案

在此线程中,建议使用几种方法进行“安全”删除。

我从中挑选了我最喜欢的一个,并为您的代码实现了它,如下所示:

correction =  {u'drug.ind': u'Necrosis', "date": "exp"}
drugs =  [[u'drug.aus', u'Necrosis'], [u'drug.nz', u'Necrosis'], [u'drug.uk', u'Necrosis'],
          [u'drug.ind', u'Necrosis'], [u'cheapest', u'drug.ind'], [u'date', u'']]

if correction and drugs:
    for i,x in correction.items():
        for j in range(len(drugs)-1, -1, -1):
            if len(i.split(".")) > 1:  # need to do the operation only for drugs which is always given in this format
                if x == drugs[j][1]:
                    drugs.pop(j)
print(drugs)

这个的输出是:

[['cheapest', 'drug.ind'], ['date', '']]

该解决方案的关键方面在于行for j in range(len(drugs)-1, -1, -1)。我们现在遍历索引,而不是遍历那些索引处的项目我们正在以相反的顺序迭代索引(这实际上意味着我们正在以相反的顺序间接处理列表)。


推荐阅读