0

Create a list

list=[]
for i in range(0,15):
    dict={}
    dict['number']=i
    dict['key']='yes'
    list.append(dict)
print(list)

we have something like:

[{'number': 0, 'key': 'yes'}, {'number': 1, 'key': 'yes'}, {'number': 2, 'key': 'yes'}, {'number': 3, 'key': 'yes'}, {'number': 4, 'key': 'yes'}, {'number': 5, 'key': 'yes'}, {'number': 6, 'key': 'yes'}, {'number': 7, 'key': 'yes'}, {'number': 8, 'key': 'yes'}, {'number': 9, 'key': 'yes'}, {'number': 10, 'key': 'yes'}, {'number': 11, 'key': 'yes'}, {'number': 12, 'key': 'yes'}, {'number': 13, 'key': 'yes'}, {'number': 14, 'key': 'yes'}]

Then trying to remove all dictionary that contains 'key'=='yes'

for i in list:
    if i['key']=='yes':
            list.remove(i)
print(list)

we have:

[{'number': 1, 'key': 'yes'}, {'number': 3, 'key': 'yes'}, {'number': 5, 'key': 'yes'}, {'number': 7, 'key': 'yes'}, {'number': 9, 'key': 'yes'}, {'number': 11, 'key': 'yes'}, {'number': 13, 'key': 'yes'}]

which only removes even numbers, WHY?

Pedro Lobito
  • 94,083
  • 31
  • 258
  • 268
NumberVII
  • 5
  • 2

3 Answers3

0

That is happening because you are changing iterable object while the cycle. It's better not to remove an element from your list, but append elements you need to a new list and reverse your condition:

new_list = []
for i in list:
    if i['key']!='yes':
            new_list.append(i)

Or you can use filter for that purpose as well without for loop:

list = filter(lambda x: x['key'] != 'yes', list)
Sergey Pugach
  • 5,561
  • 1
  • 16
  • 31
0

This is happening because the loop you are using to delete the element. You are changing the list while iterating over it.

Better explanation if you add a print statement in the loop you will get the insight what is happening:

for i in list:
    print(i)
    if i['key']=='yes':
            list.remove(i)

The output is:

{'number': 3, 'key': 'yes'}
{'number': 7, 'key': 'yes'}
{'number': 11, 'key': 'yes'}

To solve this you can add element to new list and the delete it after.

to_delete_list = []
for i in list:
    if i['key']!='yes':
            to_delete_list.append(i)
ankur09011
  • 453
  • 3
  • 12
0

You should never iterate through the list you want to remove items on. When you do this, you need to be very careful. We'll take an example so that you can see it more clearly.

Look at the code below, and look what is happening :

arr = list(range(10))
for index, elem in enumerate(arr):
    print("Before deletion : {}".format(arr))
    arr.remove(elem)
    print("Element deleted : {}".format(elem))
    print("After deletion : {}".format(arr), end='\n\n')
# Before deletion : [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
# Element deleted : 0
# After deletion : [1, 2, 3, 4, 5, 6, 7, 8, 9]

# Before deletion : [1, 2, 3, 4, 5, 6, 7, 8, 9]
# Element deleted : 2
# After deletion : [1, 3, 4, 5, 6, 7, 8, 9]

# Before deletion : [1, 3, 4, 5, 6, 7, 8, 9]
# Element deleted : 4
# After deletion : [1, 3, 5, 6, 7, 8, 9]

# Before deletion : [1, 3, 5, 6, 7, 8, 9]
# Element deleted : 6
# After deletion : [1, 3, 5, 7, 8, 9]

# Before deletion : [1, 3, 5, 7, 8, 9]
# Element deleted : 8
# After deletion : [1, 3, 5, 7, 9]

At the first iteration. You can see that all the elements are here. Then, the element you are pointing on (here, the number 0) is getting deleted and your first element is now your second element.

And here is the step that is confusing you. You are now beginning the second iteration of your loop, but your original list has changed. You are, as expected, pointing the second element of your list, which is now the number 2 instead of the number 1 originally.

And it goes on and on and on, explaining why only approximately half of your list gets deleted.

If you have questions, comment below :)

IMCoins
  • 3,149
  • 1
  • 10
  • 25