2016-04-26 64 views
0

我有以下代码。为什么删除不能在列表中使用?

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"]) 

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

回答

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] 

因为,你可以看到,就在第三次迭代之前,a被更新并且3被转移到第二位置并且因为第二位置已经被迭代了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]

所以,像我刚才所说:它不工作,但它仅仅是它

+0

但是,如果我做'a = [1,2,3,4,5,6,7,8]'并且在e:if e%2 == 0中做:a.remove (e)',那么它工作正常..为什么? –

+0

@MayukhSarkar我用适当的推理更新了我的答案。请看一看。 – AKS

+1

非常感谢..让我的理解更加清晰.. –

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

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

for each in products[:]: 
+0

但是,如果我做了'a = [1,2,3,4,5,6,7,8]'并且在e: 2 == 0:a.remove(e)',那么它工作正常..为什么? –

+0

@MayukhSarkar *意外* - >有时它*似乎*工作正常,有时它不。 –

+0

感谢您的帮助 –

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

相关问题