Alex Rivera | Logout

Remove items from a list while iterating without using extra memory in Python

Asked 2010-04-13T11:44:12.190
10

My problem is simple: I have a long list of elements that I want to iterate through and check every element against a condition. Depending on the outcome of the condition I would like to delete the current element of the list, and continue iterating over it as usual.

I have read a few other threads on this matter. Two solutions seam to be proposed. Either make a dictionary out of the list (which implies making a copy of all the data that is already filling all the RAM in my case). Either walk the list in reverse (which breaks the concept of the alogrithm I want to implement).

Is there any better or more elegant way than this to do it ?

def walk_list(list_of_g):
    g_index = 0
    while g_index < len(list_of_g):
        g_current = list_of_g[g_index]
        if subtle_condition(g_current):
            list_of_g.pop(g_index)
        else:
            g_index = g_index + 1
Edit
Report

3 Answers

3

The built-in filter function is made just to do this:

list_of_g = filter(lambda x: not subtle_condition(x), list_of_g)
answered 2010-04-13T11:51:33.823
1

For simplicity, use a list comprehension:

def walk_list(list_of_g):
    return [g for g in list_of_g if not subtle_condition(g)]

Of course, this doesn't alter the original list, so the calling code would have to be different.

If you really want to mutate the list (rarely the best choice), walking backwards is simpler:

def walk_list(list_of_g):
    for i in xrange(len(list_of_g), -1, -1):
        if subtle_condition(list_of_g[i]):
            del list_of_g[i]
answered 2010-04-13T11:47:42.690
0

Sounds like a really good use case for the filter function.

def should_be_removed(element):
  return element > 5

a = range(10)
a = filter(should_be_removed, a)

This, however, will not delete the list while iterating (nor I recommend it). If for memory-space (or other performance reasons) you really need it, you can do the following:

i = 0
while i < len(a):
    if should_be_removed(a[i]):
        a.remove(a[i])
    else:
        i+=1
    print a
answered 2010-04-13T11:53:57.327

Your Answer