0

If I have a bit of Python like:

n = [1, 3, 5, 1]
n.remove(1)
print n

n will return [3, 5, 1] because .remove() quits after it finds its first match. What could I do to return just [3, 5], having found all matches (or in this case, all the 1s)?

awesame
  • 84
  • 2
  • 13

5 Answers5

11

If creating a new list is fine:

n = [x for x in n if x != 1]

Of course you could also use slice assignment to modify the list in place:

n[:] = [x for x in n if x != 1]
Andrew Clark
  • 202,379
  • 35
  • 273
  • 306
  • Unless I'm mistaken and there's some interpreter optimization going on, that's not technically an in place operation. You construct a list in a new region in memory, then copy it in to the memory footprint of the original list. – Silas Ray Jan 30 '14 at 22:09
  • Yeah, there is a temporary copy made for the slice assignment. When I say "in place" I mean that `n` is still referencing the same list (with modified contents), rather than having `n` bound to a completely different list. It really only matters if there are other references to the list. – Andrew Clark Jan 30 '14 at 22:19
2

use filter function

n = [1, 3, 5, 1]
filter(lambda a:a is not 1,n)
[3,5]

edit

n = [1, 3, 5, 1]
filter(lambda a:a != 1,n)
[3,5]
markcial
  • 9,041
  • 4
  • 31
  • 41
  • 5
    `is not` tests (non)identity, not (in)equality. You want `a != 1` instead-- it only works on `1` by fluke, basically (see [here](http://stackoverflow.com/questions/306313/python-is-operator-behaves-unexpectedly-with-integers), for example.) – DSM Jan 30 '14 at 21:55
  • fixed, didn't knew about identity of variables, will take more care, thanks – markcial Jan 30 '14 at 21:59
2

Simple List Comprehension -

>>> n = [1, 3, 5, 1]
>>> n = [e for e in n if e != 1]
>>> n
[3, 5]

If you wanted to remove more than one elements -

>>> g = [1,3]
>>> n = [e for e in n if e not in g]
>>> n
[5]
RyPeck
  • 7,830
  • 3
  • 38
  • 58
0

This is not how I'd normally do this, but:

n = [1, 3, 5, 1]
REMOVECHAR = 1
while REMOVECHAR in n:
    n.remove(REMOVECHAR)
# could also do:
# while 1:
#     try: n.remove(REMOVECHAR)
#     except ValueError as e: break

If I were doing it, I would use a list comp to make a new list.

n = [1,3,5,1]
REMOVECHAR = 1
nn = [element for element in n if element != REMOVECHAR]
Adam Smith
  • 52,157
  • 12
  • 73
  • 112
  • Why have you capitalised `REMOVECHAR`? – rlms Jan 30 '14 at 22:00
  • Because I'm using it as a constant, which are written in UPPERCASE as per [PEP8](http://www.python.org/dev/peps/pep-0008/#constants) though I suppose technically I should have used `REMOVE_CHAR` :P – Adam Smith Jan 30 '14 at 22:02
  • `try\except` version is better, as you don't have to do the O(n) membership check every iteration. Though still, inefficient since you are still traversing every element that precedes a match even if you've already checked it until all instances are removed. – Silas Ray Jan 30 '14 at 22:05
  • But less obvious to a new coder who is asking how to remove all members of a list, which is why I presented it as an alternate implementation in comments :). I'd wager that `try/except` is faster than the list comprehension too except perhaps for very large lists with many occurrences of `REMOVECHAR` – Adam Smith Jan 30 '14 at 22:07
0

You could iterate backwards through the list and pop elements that match.

def remove_all_in_place(target, sequence):
    cursor = len(target) - 1
    while cursor >= 0:
        if sequence[cursor] == target:
            sequence.pop(cursor)
        cursor -= 1

List comprehensions might be faster since they are optimized, but they aren't in-place operations. For native Python implementations, I think this would be fastest, as well as being true in-place.

Silas Ray
  • 25,682
  • 5
  • 48
  • 63
  • I've always followed the rule "Don't operate on a list while iterating on it." Does your `lst.pop(needle)` actually work safely while iterating through `lst`? – Adam Smith Jan 30 '14 at 22:50
  • 1
    That's why I go backwards through it. Going forwards would change the indexes of future elements making things more difficult. – Silas Ray Jan 31 '14 at 11:39