Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to remove list elements in a for loop in Python? [duplicate]

Tags:

python

list

I have a list

a = ["a", "b", "c", "d", "e"]

I want to remove elements in this list in a for loop like below:

for item in a:
    print(item)
    a.remove(item)

But it doesn't work. What can I do?

like image 713
alwbtc Avatar asked May 19 '12 13:05

alwbtc


People also ask

How do you remove duplicates from a list in a loop in Python?

You can make use of a for-loop that we will traverse the list of items to remove duplicates. The method unique() from Numpy module can help us remove duplicate from the list given. The Pandas module has a unique() method that will give us the unique elements from the list given.

How do you remove an element from a list in a loop in Python?

We can delete multiple elements from a list while iterating, but we need to make sure that we are not invalidating the iterator. So either we need to create a copy of the list for iteration and then delete elements from the original list, or we can use the list comprehension or filter() function to do the same.

How do I remove duplicates from a list and keep it in Python?

If you want to preserve the order while you remove duplicate elements from List in Python, you can use the OrderedDict class from the collections module. More specifically, we can use OrderedDict. fromkeys(list) to obtain a dictionary having duplicate elements removed, while still maintaining order.


4 Answers

You are not permitted to remove elements from the list while iterating over it using a for loop.

The best way to rewrite the code depends on what it is you're trying to do.

For example, your code is equivalent to:

for item in a:
    print(item)
a[:] = []

Alternatively, you could use a while loop:

while a:
    print(a.pop())

I'm trying to remove items if they match a condition. Then I go to next item.

You could copy every element that doesn't match the condition into a second list:

result = []
for item in a:
    if condition is False:
        result.append(item)
a = result

Alternatively, you could use filter or a list comprehension and assign the result back to a:

a = filter(lambda item:... , a)

or

a = [item for item in a if ...]

where ... stands for the condition that you need to check.

like image 72
NPE Avatar answered Oct 17 '22 17:10

NPE


Iterate through a copy of the list:

>>> a = ["a", "b", "c", "d", "e"]
>>> for item in a[:]:
    print(item)
    if item == "b":
        a.remove(item)

a
b
c
d
e
>>> print(a)
['a', 'c', 'd', 'e']
like image 34
Alex L Avatar answered Oct 17 '22 18:10

Alex L


As other answers have said, the best way to do this involves making a new list - either iterate over a copy, or construct a list with only the elements you want and assign it back to the same variable. The difference between these depends on your use case, since they affect other variables for the original list differently (or, rather, the first affects them, the second doesn't).

If a copy isn't an option for some reason, you do have one other option that relies on an understanding of why modifying a list you're iterating breaks. List iteration works by keeping track of an index, incrementing it each time around the loop until it falls off the end of the list. So, if you remove at (or before) the current index, everything from that point until the end shifts one spot to the left. But the iterator doesn't know about this, and effectively skips the next element since it is now at the current index rather than the next one. However, removing things that are after the current index doesn't affect things.

This implies that if you iterate the list back to front, if you remove an item at the current index, everything to it's right shifts left - but that doesn't matter, since you've already dealt with all the elements to the right of the current position, and you're moving left - the next element to the left is unaffected by the change, and so the iterator gives you the element you expect.

TL;DR:

>>> a = list(range(5))
>>> for b in reversed(a):
    if b == 3:
        a.remove(b)
>>> a
[0, 1, 2, 4]

However, making a copy is usually better in terms of making your code easy to read. I only mention this possibility for sake of completeness.

like image 29
lvc Avatar answered Oct 17 '22 19:10

lvc


import copy

a = ["a", "b", "c", "d", "e"]

b = copy.copy(a)

for item in a:
    print(item)
    b.remove(item)
a = copy.copy(b)

Works: to avoid changing the list you are iterating on, you make a copy of a, iterate over it and remove the items from b. Then you copy b (the altered copy) back to a.

like image 6
user3848191 Avatar answered Oct 17 '22 18:10

user3848191