1

My question can looks a bit weird and easy, but I can't find a satisfying answer. I want to iterate on a list, and remove elements from it. The problem happens when there is one element left in the list after a deletion: the loop will not iterate on the last element, just as if the list was empty.

I am using a for .. in .. like in the following example:

def test_remove(self):
    """Test to remove all values from a list."""
    test = [4, 5]
    [test.remove(i) for i in test]
    print test

I am getting the following output:

[5]

Does it mean that iterating like I am doing on a list doesn't dynamically resize the list when an element is deleted (same thing is happening using for i in range()) ? Or it is just because i am simply reaching i = len, and so I can't go further ?

I could always cheat and check when the len is equal to 1 but I would like to understand if there is a more beautiful way to do this.

Thank you very much.

Ecterion
  • 161
  • 3
  • 19

7 Answers7

2

The problem is that as you remove the items from the list, the other items change positions in it, resulting in skipping some of them as the loop keeps on iterating. Try with more elements and you will see how the skipping follows a pattern.

To avoid this you need to iterate the list differently and in my opinion backwards.

A way to do it could be the following:

    i = len(test)-1
    while (i>=0):
        del test[i]
        i-=1
    print(test)
George Bou
  • 568
  • 1
  • 8
  • 17
  • Yes thats what I have finally done. I thought for in was able to avoid this kind of loop structuration. Thanks :) – Ecterion Jun 05 '17 at 08:06
1

While you can't do a for in loop or a list comprehension while making modifications to that iterable. The simplest is to use a while loop

while len(test):
    test.pop()
e4c5
  • 52,766
  • 11
  • 101
  • 134
  • Thanks for the answer. However in my case I can't use .pop() in order to remove an item from my list, as I have to start at the beginning of the list and may or may not remove the item when I iterate on it. It depends on some condition. I guess I will do a simple length check at the moment. – Ecterion Jun 05 '17 at 07:54
0

It's not just the last element, it is every odd element - test it on a longer list. This is because as you delete elements, all other elements shift positions. The best way around it is probably to copy the elements you don't want to remove to a new list.

Błotosmętek
  • 12,717
  • 19
  • 29
0

You can use the following code:

while len(test):
   if condition_to_remove is True: 
        test.pop()

Following question has some good answers that might help you:

Remove items from a list while iterating

abhinsit
  • 3,214
  • 4
  • 21
  • 26
0

As your description you can also go through this way.

ls = [1,2,3,4]
ls_length = len(ls)
i = 0  
condition_satisfied = True
while ls_length:
    if i<ls_length:
        test_num = ls[i]
        i = i + 1
        if condition_satisfied:
            ls.remove(test_num)
            ls_length = len(ls)
            i = 0
print(ls)
R.A.Munna
  • 1,699
  • 1
  • 15
  • 29
0

Use:

for (Iterator<String> iter = list.listIterator(); iter.hasNext(); ){ 
    String a = iter.next();  
    if (...) {            
        iter.remove();  
        }    
    }

Use the code as above; it will work. It worked for me in removing all elements from the list.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Sangamesh
  • 1
  • 1
0

Easy using the index of the element:

for index in range(0,len(my_list)):
    item = my_list[index]
    if item == item_to_remove:
        my_list.remove(item_to_remove)
        index -= 1
AndyFe
  • 1