0

There are many questions similar to this (here is one) but the solutions I've seen use list comprehension or filter and those ways generate a new list (or a new iterator in the case of filter in Python 3.x). There are solutions that remove instances by modifying the list itself (like this, and this), and those would be my last resort. However, I am asking to see if there a more elegant ("Pythonic" as another question calls it) way of doing it.

Why I am disregarding solutions that generate a new list: I am iterating over a collection of lists, and Python allows me to modify the "current" list I am iterating over, but not to replace it entirely:

>>> ll= [[1,2,3], [2,3,4], [4,5,6]]

>>> for l in ll:
        if l[0] == 2:
            l = [10]
>>> ll
[[1, 2, 3], [2, 3, 4], [4, 5, 6]]   #replacement didn't happen

>>> for l in ll:
        if l[0] == 2:
            l.remove(2)
>>> ll
[[1, 2, 3], [3, 4], [4, 5, 6]]   #modification succeeded 
Community
  • 1
  • 1
Anas Elghafari
  • 1,062
  • 1
  • 10
  • 20
  • 3
    So you want to remove elements from a list, without creating a new list or modifying the existing list? That excludes everything. – lxop Apr 09 '13 at 07:42
  • Haha. Sorry, I see I didn't clarify (I'll edit). No, of course I am looking for a way to modify the list just a more pythonic way than, for example, the question here: http://stackoverflow.com/questions/1157106/remove-all-occurences-of-a-value-from-a-python-list – Anas Elghafari Apr 09 '13 at 07:46
  • 1
    Do you know what functional means? – jamylak Apr 09 '13 at 09:03
  • Good point; I edited. – Anas Elghafari Apr 14 '13 at 20:22

1 Answers1

6

You need to use slice assignment to replace all list elements instead of the list itself:

for l in ll:
    if l[0] == 2:
        l[:] = [10]

The [:] part turns this into slice assignment; instead of replacing the reference l points to, you replace all elements contained in l with the new list.

Demo:

>>> ll= [[1,2,3], [2,3,4], [4,5,6]]
>>> for l in ll:
...     if l[0] == 2:
...         l[:] = [10]
... 
>>> ll
[[1, 2, 3], [10], [4, 5, 6]]
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • Thanks, this is what I was looking for. Now I can make use of list comprehension to remove all instances of an element through modification, not generating a new list: >>> ll= [[1,2,3], [2,3,4,2], [4,5,6]] >>> for l in ll: if l[0] == 2: l[:] = [x for x in l if x!=2] >>> ll [[1, 2, 3], [3, 4], [4, 5, 6]] – Anas Elghafari Apr 09 '13 at 07:58
  • 1
    @AnasElghafari: Or you could just do `ll = [filter(lambda x: x != 2, el) for el in ll]` – Joel Cornett Apr 09 '13 at 08:19