deleting items within a for loop - mutable indices

Discussion in 'Python' started by SnuSnu, Apr 24, 2004.

  1. SnuSnu

    SnuSnu Guest

    Okay - here's a (probably) really easy question:

    I can't do the following, so what's the best way to handle this
    case of wanting to delete within a loop?

    x = [0,1,2,3,4,5,6,7,8]
    deletion_list = [2,7,8]

    for i in deletion_list:
    del x

    This obviously doesn't work because the list keeps changing
    each time I delete something, so the indices are no longer valid
    after the first delete (so I get an IndexError on teh last delete).

    My hack is to do this first (which makes sure that the higher indices
    are deleted first), but this is not very elegant or quick:

    deletion_list.sort()
    deletion_list.reverse()
    # BTW: It's a shame I can't do deletion_list.sort().reverse()

    Is there a simple solution?

    (It would be nice to do something like
    del x[2,7,8] # or..
    del [*deletion_list]
    )

    Thanks.
     
    SnuSnu, Apr 24, 2004
    #1
    1. Advertising

  2. SnuSnu wrote:

    > Okay - here's a (probably) really easy question:
    >
    > I can't do the following, so what's the best way to handle this
    > case of wanting to delete within a loop?
    >
    > x = [0,1,2,3,4,5,6,7,8]
    > deletion_list = [2,7,8]
    >
    > for i in deletion_list:
    > del x
    >
    > This obviously doesn't work because the list keeps changing
    > each time I delete something, so the indices are no longer valid
    > after the first delete (so I get an IndexError on teh last delete).


    The solution is usually to either iterate over an explicit copy of the
    list, or use functional means to build the final list up from the
    original list without mutating it at all.

    In this case it's probably best to just iterate backwards over the
    indices, since you know what you're getting and can control the order in
    which you delete the items.

    > deletion_list.sort()
    > deletion_list.reverse()
    > # BTW: It's a shame I can't do deletion_list.sort().reverse()


    This is a deliberate design decision. These methods are made to return
    None so you're explicitly aware that they mutate the object, rather than
    return a duplicate. You can always define your own functional version:

    def mySort(seq):
    result = seq[:]
    result.sort()
    return result

    --
    __ Erik Max Francis && && http://www.alcyone.com/max/
    / \ San Jose, CA, USA && 37 20 N 121 53 W && AIM erikmaxfrancis
    \__/ Awards are merely the badges of mediocrity.
    -- Charles Ives
     
    Erik Max Francis, Apr 24, 2004
    #2
    1. Advertising

  3. SnuSnu

    Dan Bishop Guest

    SnuSnu <> wrote in message news:<4089cb21$>...
    > Okay - here's a (probably) really easy question:
    >
    > I can't do the following, so what's the best way to handle this
    > case of wanting to delete within a loop?
    >
    > x = [0,1,2,3,4,5,6,7,8]
    > deletion_list = [2,7,8]
    >
    > for i in deletion_list:
    > del x
    >
    > This obviously doesn't work because the list keeps changing
    > each time I delete something, so the indices are no longer valid
    > after the first delete (so I get an IndexError on teh last delete).


    for i in deletion_list:
    x = None
    x = [num for num in x if num is not None]
     
    Dan Bishop, Apr 24, 2004
    #3
  4. SnuSnu <> wrote in message news:<4089cb21$>...
    > Okay - here's a (probably) really easy question:
    >
    > I can't do the following, so what's the best way to handle this
    > case of wanting to delete within a loop?
    >
    > x = [0,1,2,3,4,5,6,7,8]
    > deletion_list = [2,7,8]
    >
    > for i in deletion_list:
    > del x
    >
    > This obviously doesn't work because the list keeps changing
    > each time I delete something, so the indices are no longer valid
    > after the first delete (so I get an IndexError on teh last delete).
    >
    > My hack is to do this first (which makes sure that the higher indices
    > are deleted first), but this is not very elegant or quick:
    >
    > deletion_list.sort()
    > deletion_list.reverse()
    > # BTW: It's a shame I can't do deletion_list.sort().reverse()
    >
    > Is there a simple solution?
    >
    > (It would be nice to do something like
    > del x[2,7,8] # or..
    > del [*deletion_list]
    > )
    >
    > Thanks.


    Eh, do you want to delete the elements in the deletion list from x, or
    delete the elements in x which are at the location indicated in the
    deletion list? Your example doesn't differentiate.

    Anyhow, this is advice from a newbie :) but in the first case

    x = [y for y in x if not y in deletion_list]

    works well enough.

    otherwise

    tmp = [x for i in range(len(x)) if not i in deletion_list]
    x = tmp

    you could speed either up for largish lists with hashing;

    dict = {}
    for d in deletion_list:
    dict[d] = 1
    tmp = [x for i in range(len(x)) if not dict.has_key(i)]
    x = tmp

    alternatively you could make it linear in time for the number of
    deletion elements, but the performance hit from creating a bunch of
    lists hurts a bit too much, unless you don't care about order. Which
    I'm guessing you do.

    Jam
     
    James Moughan, Apr 24, 2004
    #4
  5. SnuSnu

    Roger Binns Guest

    SnuSnu wrote:
    > are deleted first), but this is not very elegant or quick:


    Here is a list comprehension that makes a new list
    without the deletion_list items. It does have the virtue
    of being a one liner :)

    newx=[x for i in range(len(x)) if i not in deletion_list]

    You will need to do timings to see what method is actually
    the fastest. Don't forget to do so with list sizes the
    same as you expect to be using in your real program. Search
    archives for this group for 'timeit' to see examples of
    how to do timings.

    (I think that the size of the deletion_list as a proportion
    of the original list is what best determines the relative
    speeds of the various methods available).

    Roger
     
    Roger Binns, Apr 24, 2004
    #5
  6. Hello,

    this should work:

    for i in deletion_list:
    x.remove(i)

    Matuka

    "SnuSnu" <> wrote in message
    news:4089cb21$...
    > Okay - here's a (probably) really easy question:
    >
    > I can't do the following, so what's the best way to handle this
    > case of wanting to delete within a loop?
    >
    > x = [0,1,2,3,4,5,6,7,8]
    > deletion_list = [2,7,8]
    >
    > for i in deletion_list:
    > del x
    >
    > This obviously doesn't work because the list keeps changing
    > each time I delete something, so the indices are no longer valid
    > after the first delete (so I get an IndexError on teh last delete).
    >
    > My hack is to do this first (which makes sure that the higher indices
    > are deleted first), but this is not very elegant or quick:
    >
    > deletion_list.sort()
    > deletion_list.reverse()
    > # BTW: It's a shame I can't do deletion_list.sort().reverse()
    >
    > Is there a simple solution?
    >
    > (It would be nice to do something like
    > del x[2,7,8] # or..
    > del [*deletion_list]
    > )
    >
    > Thanks.
    >
     
    Henk-Jan de Jong, Apr 24, 2004
    #6
  7. James Moughan wrote:

    > you could speed either up for largish lists with hashing;
    >
    > dict = {}
    > for d in deletion_list:
    > dict[d] = 1
    > tmp = [x for i in range(len(x)) if not dict.has_key(i)]
    > x = tmp


    If order doesn't matter and the items are unique you may wish to use
    sets.Set from python 2.3 instead of a dict:
    >>> from sets import Set
    >>> set = Set(['a', 'b', 2, 42])
    >>> for item in deletion_list:

    .... set.discard(item)
    ....
    >>> print set

    Set(['b', 42])

    --
    Steven Rumbalski
    news AT rumbalski DOT com
     
    Steven Rumbalski, Apr 25, 2004
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. NFish
    Replies:
    6
    Views:
    15,331
    Andrey Tarasevich
    Nov 7, 2003
  2. Replies:
    5
    Views:
    339
    Bengt Richter
    Dec 10, 2004
  3. blumenkraft

    delete items from list by indices

    blumenkraft, Sep 23, 2009, in forum: Python
    Replies:
    4
    Views:
    323
    blumenkraft
    Sep 23, 2009
  4. mt

    Multiple indices in for loop

    mt, Mar 29, 2011, in forum: C Programming
    Replies:
    3
    Views:
    347
    J. J. Farrell
    Mar 30, 2011
  5. Isaac Won
    Replies:
    9
    Views:
    397
    Ulrich Eckhardt
    Mar 4, 2013
Loading...

Share This Page