[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

Re: [pygame] Iterate over list and delete



A couple of options still then.

The simplest on paper is #3 of your original options, but as you mentioned, list.remove() has problems (and bigger problems if you are working with potentially duplicate items).

A second option is stay as close to the list comprehension as possible, using either the built-in filter function or a simple clone:

def filter(input_list, check_function):
    for item in input_list:
        if check_function(item):
            yield item

This of course involves yield which you may not wish to get into yet.

The third, and probably most convenient based on where you seem to be at in the curriculum, is to do something like Ian suggested. I think there's a simpler way to do it with similar performance though I've not benched to find out; I don't think autoresizing should be too much of a concern, especially early in a class like this.

index = 0
# Could also use a for loop to avoid repeatedly len()ing:
## for _discarded in range(len(my_list)):
while index < len(my_list):
    if need_to_delete(my_list[index]):
        del my_list[index]
        # We don't need to update the index after deleting because now the next
        # item is sitting in the current slot
    else:
        index += 1

Hopefully this is helpful!

On Sun, May 20, 2018 at 6:55 PM, Irv Kalb <Irv@xxxxxxxxxxxxxx> wrote:
Thanks very much.

Is there a way to do that without the list comprehension? I'm building this as part of a class, and I will not have talked about list comprehensions up until that point.

Thanks,

Irv


On May 20, 2018, at 2:35 PM, Daniel Foerster <pydsigner@xxxxxxxxx> wrote:

I think what you're looking for is this:

my_list = [x for x in my_list if not need_to_delete(x)]

On Sun, May 20, 2018, 16:28 Irv Kalb <Irv@xxxxxxxxxxxxxx> wrote:
I am building a game where I am keeping track of many objects in a list (let's just call it "myList".  In every "frame" of my game I need to see if any objects need to be removed from myList.

I know that this code:

for item in myList:
    if needsToBeDeleted(item):
         myList.remove(item)

does not work correctly because it affects the order of list while I am iterating over it.  (Specifically, if there are two elements in a row that should be removed, the first one is removed, but the second one is skipped over.)

I have looked at many different solutions, and have found a number of different approaches, but none them seem elegant.  Here are ones that work:

1)  Build a list of indices in reverse order (  [n - 1, n -2, n - 3, ... 0] )
     Iterate over this list
          if the element at that index needs to be deleted,
                pop the element at this index

    (untested, but should work)

     indexList = list(range(0, n - 1))
     indexList.reverse()

     for index in indexList:
          if needsToBeDeleted(myList[index]):
                myList.pop(index)

    I believe this will work, but it looks very clunky.


2)  Create a tempList that starts off empty.
     Iterate through my original list.
        If an element does NOT need to be deleted, append it to the tempList. 
     Reassign the myList to the tempList
     Set the tempList to None (or delete it)

     tempList = []
     for item in myList:
         if not needsToBeDeleted(item):
             tempList.append(item)
      myList = tempList
      tempList = None

     Seems OK, but again, seems like kind of a kludge.

3)  Iterate through a copy of the list:

     for item in myList[:]:
         if needsToBeDeleted(item):
             myList.remove(item)

      This does work, but I would guess it might be slow for long lists (since it first has to duplicate a list, then when it wants to delete an element, 'remove' must search through the list to find the matching element before deleting it).  Also, it would be tricky to explain to students, because I am iterating through a copy of a list, but deleting elements from the original list.


Does anyone have an easier, more clear, reusable approach?

If not, any thoughts on which of these three approach would be most efficient and clear?  I don't have a favorite yet.

Thanks,

Irv