Reputation: 2625
I have the following code.
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"])
Now whenever I run this, it removes only one entry in the dict. For example, in this case it is removing the 2nd entry and that is SC5-01OS19_GP221_JC302_LTE_MTN
. I believe this is something related to shallow copy..Am I right ?? If not then how solve this issue?
Upvotes: 0
Views: 60
Reputation: 19861
You are removing the entry from the list while iterating over the same list. You could simply use list comprehension to keep the elements which are required:
products = [product for product in products
if product.get('Product', None) not in blacklist]
Or using filter
:
products = filter(lambda product: product.get('Product', None) not in blacklist, products)
Update regarding remove from a = [1, 2, 3, 4, 5, 6, 7, 8]
:
You say following code works:
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]
Well, it doesn't work but it is just an illusion, let's add some print statements to understand:
for e in a:
print 'Next Item: ', e
if e % 2 = 0:
a.remove(e)
print 'Current List: ', a
And, here is the output from the print
statements:
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]
As, you can see, just before the 3rd iteration the a
is updated and 3
is shifted to the 2nd position and since 2nd position is already iterated 3
never comes in the loop. And, similarly for others so the loop doesn't run 8 times but only 5 times.
If you change the order of values in a
you won't get the same behavior:
a = [1, 4, 2, 3, 6, 8, 7, 5]
Now, run the above `for loop again:
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]
So here at the end of the list the value of a
is [1, 2, 3, 8, 7, 5]
.
So like I said earlier: It doesn't work but it is just an illusion that it does
Upvotes: 1
Reputation: 690
As explained by AKS, you can use list comprehensions to filter out list elements. In addition, you can use the built in filter
function:
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]
Ultimately, the issue you're running into is that you are modifying your list as you iterate through it. This has been discussed many times, for example: Modifying list while iterating
Upvotes: 0
Reputation: 122493
for each in products:
# print each
if each['Product'] in blackList:
products.remove(each)
Here you are modifying the list while iterating over it. That would give you unexpected result. A quick fix is: iterate over a copy of the list:
for each in products[:]:
Upvotes: 1