Python: Removing list element while iterating over list [duplicate]
I'm iterating over a list of elements in Python, do some action on it, and then remove them if they meet certain criteria.
for element in somelist:
do_action(element)
if check(element):
remove_element_from_list
What should I use in place of remove_element? I have seen similar questions asked, but notice the presence of the do_action part that is to be executed for all elements and thus eliminates the solution of using filters.
Solution 1:
You could always iterate over a copy of the list, leaving you free to modify the original:
for item in list(somelist):
...
somelist.remove(item)
Solution 2:
To meet these criteria: modify original list in situ, no list copies, only one pass, works, a traditional solution is to iterate backwards:
for i in xrange(len(somelist) - 1, -1, -1):
element = somelist[i]
do_action(element)
if check(element):
del somelist[i]
Bonus: Doesn't do len(somelist)
on each iteration. Works on any version of Python (at least as far back as 1.5.2) ... s/xrange/range/ for 3.X.
Update: If you want to iterate forwards, it's possible, just trickier and uglier:
i = 0
n = len(somelist)
while i < n:
element = somelist[i]
do_action(element)
if check(element):
del somelist[i]
n = n - 1
else:
i = i + 1
Solution 3:
List comp:
results = [x for x in (do_action(element) for element in somelist) if check(element)]
Solution 4:
for element in somelist:
do_action(element)
somelist[:] = (x for x in somelist if not check(x))
If you really need to do it in one pass without copying the list
i=0
while i < len(somelist):
element = somelist[i]
do_action(element)
if check(element):
del somelist[i]
else:
i+=1
Solution 5:
You can still use filter, moving to an outside function the element modification (iterating just once)
def do_the_magic(x):
do_action(x)
return check(x)
# you can get a different filtered list
filter(do_the_magic,yourList)
# or have it modified in place (as suggested by Steven Rumbalski, see comment)
yourList[:] = itertools.ifilter(do_the_magic, yourList)