As was foretold, we've added advertisements to the forums! If you have questions, or if you encounter any bugs, please visit this thread: https://forums.penny-arcade.com/discussion/240191/forum-advertisement-faq-and-reports-thread/

(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 unionize your workplace 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 regular
    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 unionize your workplace Seattle, WARegistered User regular
    edited August 2010
    Then, as zilo said, you're doing it right.

    admanb on
Sign In or Register to comment.