Club PA 2.0 has arrived! If you'd like to access some extra PA content and help support the forums, check it out at patreon.com/ClubPA
The image size limit has been raised to 1mb! Anything larger than that should be linked to. This is a HARD limit, please do not abuse it.
Our new Indie Games subforum is now open for business in G&T. Go and check it out, you might land a code for a free game. If you're developing an indie game and want to post about it, follow these directions. If you don't, he'll break your legs! Hahaha! Seriously though.
Our rules have been updated and given their own forum. Go and look at them! They are nice, and there may be new ones that you didn't know about! Hooray for rules! Hooray for The System! Hooray for Conforming!

(Python) removing items while looping over a list?

evilmrhenryevilmrhenry Registered User regular
edited August 2010 in Help / Advice Forum
Basically, I want some way to loop over a list, while removing some or all items. Right now, I'm looping backwards, eg:
a = [1, 2, 3, 4, 5, 6, 7]
for i in range(len(a)-1, -1, -1):
     a.pop(i)
Which correctly removes all items from the list. The only problem is that it seems somewhat silly; there's no way that's the "proper" way to do this.

To be clear, code like
a = [1, 2, 3, 4, 5, 6, 7]
for pos, number in enumerate(a):
     a.pop(pos)
will only delete some items.

evilmrhenry on

Posts

  • admanbadmanb the bored genie Seattle, WARegistered User regular
    edited August 2010
    Do you have some particular reason to be looping rather than filtering? Warning: untested.
    def f(x): return false
    a = [1, 2, 3, 4, 5, 6, 7]
    a = filter(f, a)
    

    Should remove every item. Modify f(x) to return false for items you want to remove and voila.

    Here's why enumerating doesn't work, from here:
    Note that the for-in statement maintains an internal index, which is incremented for each loop iteration. This means that if you modify the list you’re looping over, the indexes will get out of sync, and you may end up skipping over items, or process the same item multiple times.

    admanb on
  • zilozilo Registered User
    edited August 2010
    You're doing it right. Using your example, if you're iterating forwards and removing a[2], when you remove it what was a[3] is now a[2] (these are lists, not arrays). Then you increment pos and look at a[3], which was a[4] before you did the remove. Iterating backwards doesn't change the indices of the elements you haven't examined yet.

    zilo on
  • evilmrhenryevilmrhenry Registered User regular
    edited August 2010
    admanb wrote: »
    Do you have some particular reason to be looping rather than filtering?
    Yes; in my code, I would be processing each entry, and removing some of them. filter() takes care of removing items, and map() would let me process each item, but I don't see a good way to do both at once.

    A better example:
    a = [1, 2, 3, 4, 5, 6]
    for i in range(len(a)-1, -1, -1):
        if a[i] % 3 == 0: a.pop(i)
        else: a[i] += 3
    


    And, yes, I know why enumerate doesn't work; I'm just looking for something that does work.

    evilmrhenry on
  • admanbadmanb the bored genie Seattle, WARegistered User regular
    edited August 2010
    Then, as zilo said, you're doing it right.

    admanb on
Sign In or Register to comment.