1

Possible Duplicate:
Removing an element from a list based on a predicate

Supposing I have a list and i want to delete from it elements that respect a condition,, how can i implement this easier?

I tried with:

for i in range (len(list)):    
     if [condition]:
        del(list[i]);

Obviously it does not work...the only solution in my mind is do to shifts to left to replace the element i want to delete and then to delete the last element.. Anyway is there a faster solution?

Community
  • 1
  • 1
shaku
  • 55
  • 3
  • 7

4 Answers4

12

How about using a list comprehension:

mylist = [x for x in mylist if not condition]
Tim Pietzcker
  • 328,213
  • 58
  • 503
  • 561
4

The simplest way is to create a copy of the list using filter:

list_removed = filter(lambda item: not condition(item), list)
Björn Pollex
  • 75,346
  • 28
  • 201
  • 283
1

I recommend @Space_C0wb0y's solution; however, for completeness I want to point out that

for i in range(len(lst)-1, -1, -1):    
    if (condition):
        del lst[i]

works properly.

Hugh Bothwell
  • 55,315
  • 8
  • 84
  • 99
  • 1
    It works, but is is O(n^2) whereas the list comprehension or `filter` calls are O(n). That may not always matter, but the list comprehension is unlikely ever to be the wrong choice. – Duncan Mar 17 '11 at 13:37
  • @Duncan: not arguing, but how do you get O(n**2)? – Hugh Bothwell Mar 17 '11 at 13:39
  • 3
    I believe it's because every time an item in the list is deleted, all the trailing items are shifted down by one. See the end of this answer for an in-place, order-preserving filter that (I think!) avoids this problem: http://stackoverflow.com/questions/5162991/list-manipulation-with-pop-python/5163010#5163010 – senderle Mar 17 '11 at 14:27
  • as @senderle says each deletion has to shuffle around pointers to every element that follows it. @senerle you can make a filter or list comprehension act on the list in-place by using a slice assignment: `lst[:] = [...]` – Duncan Mar 17 '11 at 14:52
  • @Duncan -- Ah! Slice assignment... it seems so obvious now. :) But doesn't the list comprehension still create a copy? Will using a generator expression avoid that? – senderle Mar 17 '11 at 15:27
0

If you need to modify the list in-place (so that the suggestions others have made of filter or list comprehension won't help you) then:

  1. You can avoid the outright failure of the code you give by processing elements in reverse order, so that deleting one doesn't affect the numbering of the ones processed later.

  2. Shifting the elements around to put the "dead" ones at the end is almost certainly not worth it, but if you do it you can get one more little optimization by doing a single deletion at the end to remove all the dead elements, rather than removing each one as you see it. (The gain from this is likely to be small. Deleting the last element of a list is cheap unless it happens to trigger an actual resize, which by design it doesn't do very often.)

  3. If it happens that you're deleting a lot of elements -- a substantial fraction of all the elements in the list -- then the "not worth it"s in 2 above are less obvious and you should benchmark it both ways.

Gareth McCaughan
  • 19,888
  • 1
  • 41
  • 62