2016-04-26 55 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

相關問題