为什么删除不在dicts列表上?

时间:2016-04-26 05:15:54

标签: python

我有以下代码。

import os

products =  [

        {"Product": "S65-85OS04_M2M_GP211_JC222_R6",
         "PlatformName": "winPc",
         "PlatformVariant": "eeprom",
         "DocGeneration": False,
         "BuildStatus": "Pass",
        },

        {"Product": "SC5-01OS19_GP221_JC302_LTE_MTN",
         "PlatformName": "winPc",
         "PlatformVariant": "flash",
         "DocGeneration": False,
         "BuildStatus": "Fail",
         },

        {"Product": "SC5-01OS01_GP211_JC302_LTE_TMO",
         "PlatformName": "winPc",
         "PlatformVariant": "flash",
         "DocGeneration": False,
         "BuildStatus": "Pass",
         }
    ]

class UTE(object):

    def __init__(self, workspace, products, blackList=None):
        for each in products:
            # print each
            if each['Product'] in blackList:
                products.remove(each)
        for each in products:
            print each["Product"]

if __name__ == '__main__':
    ins = UTE('ws', products, ["SC5-01OS01_GP211_JC302_LTE_TMO", "SC5-01OS19_GP221_JC302_LTE_MTN"])

现在每当我运行它时,它只会删除dict中的一个条目。例如,在这种情况下,它将删除第二个条目,即SC5-01OS19_GP221_JC302_LTE_MTN。我相信这是与浅拷贝相关的事情。我是对的吗?如果没有那么如何解决这个问题?

3 个答案:

答案 0 :(得分:1)

for each in products:
    # print each
    if each['Product'] in blackList:
        products.remove(each)

在这里,您在迭代时修改列表。这会给你意想不到的结果。快速解决方法是:迭代列表的副本:

for each in products[:]:

答案 1 :(得分:1)

您在迭代同一列表时从列表中删除条目。您可以简单地使用列表推导来保留所需的元素:

products = [product for product in products 
            if product.get('Product', None) not in blacklist]

或使用filter

products = filter(lambda product: product.get('Product', None) not in blacklist, products)

有关从a = [1, 2, 3, 4, 5, 6, 7, 8]移除的更新

您说以下代码有效:

a = [1, 2, 3, 4, 5, 6, 7, 8]
for e in a:
    if e % 2 = 0:
        a.remove(e)

print(a) # [1, 3, 5, 7]

嗯,它不起作用,但它只是一种幻觉,让我们添加一些印刷语句来理解:

for e in a:
    print 'Next Item: ', e
    if e % 2 = 0:
        a.remove(e)

    print 'Current List: ', a

而且,这是print语句的输出:

Next Item:  1
Current List:  [1, 2, 3, 4, 5, 6, 7, 8]
Next Item:  2
Current List:  [1, 3, 4, 5, 6, 7, 8]
Next Item:  4
Current List:  [1, 3, 5, 6, 7, 8]
Next Item:  6
Current List:  [1, 3, 5, 7, 8]
Next Item:  8
Current List:  [1, 3, 5, 7]

正如你可以看到的那样,在第3次迭代之前,a被更新,3被转移到第2个位置,因为第2个位置已经被迭代3永远不会进入环。并且,与其他人类似,因此循环不会运行8次,而只会运行5次。

如果更改a中的值顺序,则不会出现相同的行为:

a = [1, 4, 2, 3, 6, 8, 7, 5]

现在,再次运行上面的`for循环:

Next Item:  1
Current List:  [1, 4, 2, 3, 6, 8, 7, 5]
Next Item:  4
Current List:  [1, 2, 3, 6, 8, 7, 5]
Next Item:  3
Current List:  [1, 2, 3, 6, 8, 7, 5]
Next Item:  6
Current List:  [1, 2, 3, 8, 7, 5]
Next Item:  7
Current List:  [1, 2, 3, 8, 7, 5]
Next Item:  5
Current List:  [1, 2, 3, 8, 7, 5]

因此,在列表末尾,a的值为[1, 2, 3, 8, 7, 5]

就像我之前说的那样:它不起作用,但它只是一种错觉

答案 2 :(得分:0)

如AKS所述,您可以使用列表推导来过滤列表元素。此外,您可以使用内置的filter函数:

some_integers = range(15)

# via filter
odd_integers = filter(lambda i: i%2 != 0, some_integers)

# via list comprehension
odd_integers = [num for num in some_integers if num %2 != 0]

最终,您遇到的问题是您在迭代时修改列表。这已经多次讨论过,例如:Modifying list while iterating