11

My problem is I have a list eg.

lst = [2, 5, 7, 12, 13]


lst.pop(3) #12
lst.pop(4) #13

Because lst[3] has been removed lst[4] is no longer there (out of range). This gives me an error. Now I know you could say change your code to this:...

lst.pop(4) #13
lst.pop(3) #12

...and it ill fix the error, but my problem is my actual code is 'popping' random numbers so it needs to be done all at the same time to avoid error.

Is there any method of 'popping' at the same time?...like something similar to this:

lst.pop(3, 4) #12 and 13 at once

Thanks for any answers.

Bhargav Rao
  • 50,140
  • 28
  • 121
  • 140
Greg Peckory
  • 7,700
  • 21
  • 67
  • 114

5 Answers5

12

You can use a list comprehension to rebuild the list:

indices = {3, 4}
newlist = [v for i, v in enumerate(oldlist) if i not in indices]

I used a set for the indices here, as set membership testing is faster than with a list.

Note that a delete (best done with del lst[index]) partially rebuilds the list as well; doing so with one loop in a list comprehension can be more efficient.

Demo:

>>> oldlist = [2, 5, 7, 12, 13]
>>> indices = {3, 4}
>>> [v for i, v in enumerate(oldlist) if i not in indices]
[2, 5, 7]
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
4

You can remove them with a list comprehension, which will create a new list:

>>> lst = [2, 5, 7, 12, 13]
>>> [v for i, v in enumerate(lst) if i not in {4,3}]
[2, 5, 7]

You just have to assign this new list to lst again.

Maxime Lorant
  • 34,607
  • 19
  • 87
  • 97
0

You could use numpy indexing for this.

Eelco Hoogendoorn
  • 10,459
  • 1
  • 44
  • 42
0

If you really want to do this by deleting in-place, the obvious answer is to sort the indices to remove:

>>> lst = [2, 5, 7, 12, 13]
>>> indices = {3, 4}
>>> for index in sorted(indices, reverse=True):
...     del lst[index]
>>> print(lst)
[2, 5, 7]

However, note that this is twice as much code as Martijn's list comprehension. And if you're trying to do things this way as an optimization, (a) it's almost certainly a premature optimization, and (b) it's very likely a pessimization instead.

If you're doing this because some other code has a reference to lst, and you need it to see the changes, you can still use a list comprehension, together with slice assignment:

>>> lst[:] = [v for i, v in enumerate(lst) if i not in indices]

Here, we're creating a new list, then replacing the subslice representing the entire contents of lst with that new list.

abarnert
  • 354,177
  • 51
  • 601
  • 671
0
lst = [2, 5, 7, 12, 13]

indexes = [3, 4]
to_del = object()

for index in indexes:
    lst[index] = to_del

for _ in indexes:
    lst.remove(to_del)

print(lst)

[2, 5, 7]
Omid Raha
  • 9,862
  • 1
  • 60
  • 64
  • 2
    If you want a safe sentinel, you can always use `to_del = object()`. The result will never compare (or hash) equal to any object except itself. – abarnert Jan 09 '14 at 23:13