Python: Removing list element while iterating over list

PythonList

Python Problem Overview


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.

Python Solutions


Solution 1 - Python

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 - Python

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 - Python

List comp:

results = [x for x in (do_action(element) for element in somelist) if check(element)]

Solution 4 - Python

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 - Python

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)

Solution 6 - Python

Another way of doing so is:

while i<len(your_list):
    if #condition :
        del your_list[i]
    else:
        i+=1

So, you delete the elements side by side while checking

Solution 7 - Python

You can make a generator that returns everything that isn't removed:

def newlist(somelist):
    for element in somelist:
        do_action(element)
        if not check(element):
            yield element

Solution 8 - Python

Why not rewrite it to be

for element in somelist: 
   do_action(element)  

if check(element): 
    remove_element_from_list

See this question for how to remove from the list, though it looks like you've already seen that https://stackoverflow.com/questions/1207406/remove-items-from-a-list-while-iterating-in-python

Another option is to do this if you really want to keep this the same

newlist = [] 
for element in somelist: 
   do_action(element)  

   if not check(element): 
      newlst.append(element)

Solution 9 - Python

Not exactly in-place, but some idea to do it:

a = ['a', 'b']

def inplace(a):
    c = []
    while len(a) > 0:
        e = a.pop(0)
        if e == 'b':
            c.append(e)
    a.extend(c)

You can extend the function to call you filter in the condition.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionScrontchView Question on Stackoverflow
Solution 1 - PythonbluepnumeView Answer on Stackoverflow
Solution 2 - PythonJohn MachinView Answer on Stackoverflow
Solution 3 - PythonzeekayView Answer on Stackoverflow
Solution 4 - PythonJohn La RooyView Answer on Stackoverflow
Solution 5 - PythonRiccardo GalliView Answer on Stackoverflow
Solution 6 - PythonAswin MurugeshView Answer on Stackoverflow
Solution 7 - PythonMark RansomView Answer on Stackoverflow
Solution 8 - PythondfbView Answer on Stackoverflow
Solution 9 - PythonMichał FitaView Answer on Stackoverflow