2016-04-26 6 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"]) 

これを実行するたびに、dictの1つのエントリだけが削除されます。たとえば、この場合は2番目のエントリが削除されており、それは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] 

まあ、それは動作しませんが、それは単なる錯覚である、のは、理解するためにいくつかのprint文を追加してみましょう:

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内の値の順序を変更する場合は、同じ動作得ることはありません。もう一度forループ `上記を実行して、今すぐ

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

を:

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]です。

だから私は以前言ったように:は、それが動作しませんが、AKSで説明したように、あなたはリストの要素をフィルタリングするために、リストの内包表記を使用することができます

+0

しかし、もし私が 'a = [1,2,3,4,5,6,7,8]'を実行し、 'for e in a: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]'を実行し、 'for e in a:if e% 2 == 0:a.remove(e) '、次に正常に動作します。 –

+0

@MayukhSarkar *予期しない* - 時にはうまくいくように見えますが、時にはうまくいきません。 –

+0

助けてくれてありがとう –

0

それがないということだけで錯覚です。また、あなたは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

関連する問題