# How to remove multiple indexes from a list at the same time? [duplicate]

14.8k Views
• 226

You need to do this in a loop, there is no built-in operation to remove a number of indexes at once.

Your example is actually a contiguous sequence of indexes, so you can do this:

``````del my_list[2:6]
``````

which removes the slice starting at 2 and ending just before 6.

It isn't clear from your question whether in general you need to remove an arbitrary collection of indexes, or if it will always be a contiguous sequence.

If you have an arbitrary collection of indexes, then:

``````indexes = [2, 3, 5]
for index in sorted(indexes, reverse=True):
del my_list[index]
``````

Note that you need to delete them in reverse order so that you don't throw off the subsequent indexes.

• 1
• +1 How would this differ if instead of `del my_list[index]` we used `my_list.pop(index)`? Would it matter? In terms of efficiency or semantics?
• Please excuse my comment, I'm learning Python, but Python reindex the array while looping for delete ? Why if you loop in normal order it raise an undefined offset exception ?
• @kitensei It does reindex, but because sorts the indexes in reverse order first, we're removing from the right-hand end of the list, so we're never reindexing an element before we delete it.
• 2
• Looping over indices backwards. Genius! I was here dreaming up some ridiculous situation of decrementing indices as I went along, when this was so much more elegant!
``````remove_indices = [1,2,3]
somelist = [i for j, i in enumerate(somelist) if j not in remove_indices]
``````

Example:

``````In [9]: remove_indices = [1,2,3]

In [10]: somelist = range(10)

In [11]: somelist = [i for j, i in enumerate(somelist) if j not in remove_indices]

In [12]: somelist
Out[12]: [0, 4, 5, 6, 7, 8, 9]
``````
• 1
• As @C.Yduqoli points out below, this is the most efficient solution (we don't need to keep rebuilding the list), but you must convert `remove_indices` to a `set` first!

There wasn't much hint on performance for the different ways so I performed a test on removing 5000 items from 50000 in all 3 generally different approaches, and for me numpy was the winner (if you have elements that fit in numpy):

• 7.5 sec for the enumerated list comprehension [4.5 sec on another PC]
• 0.08 sec for deleting items in reverse order [0.017 (!) sec]
• 0.009 sec for numpy.delete [0.006 sec]

Here's the code I timed (in the third function conversion from/to list may be removed if working directly on numpy arrays is ok):

``````import time
import numpy as np
import random

def del_list_indexes(l, id_to_del):
somelist = [i for j, i in enumerate(l) if j not in id_to_del]
return somelist

def del_list_inplace(l, id_to_del):
for i in sorted(id_to_del, reverse=True):
del(l[i])

def del_list_numpy(l, id_to_del):
arr = np.array(l, dtype='int32')
return list(np.delete(arr, id_to_del))

l = range(50000)
random.shuffle(l)
remove_id = random.sample(range(len(l)), 5000) # 10% ==> 5000

# ...
``````
• 1
• `del_list_indexes` should be much faster if you convert `id_to_del` to a set first.
• 1
• @C.Yduqoli The times I get if using a `set` for `enumerate` are: `enumerate` = 0.0041, `del` = 0.035, `numpy` = 0.0079, which has enumerate as the fastest as expected.

If they're contiguous, you can just do

``````x[2:6] = []
``````

If you want to remove noncontiguous indexes, it's a little trickier.

``````x = [v for i,v in enumerate(x) if i not in frozenset((2,3,4,5))]
``````
• Yea, which could skip out of bounds, generally not a good thing to do.
• 1
• As a note, the reason you have to do it with an enumerate is because you can't delete on something you're iterating over, that would be bad.
• 1
• @Trick Technically, that's only true if you're using a real iterator. If you use a simple int to maintain your position in the list, there are no problems, except that the index will skip if you delete something at a position lower than the current position.

If you can use numpy, then you can delete multiple indices:

``````>>> import numpy as np
>>> a = np.arange(10)
>>> np.delete(a,(1,3,5))
array([0, 2, 4, 6, 7, 8, 9])
``````

and if you use `np.r_` you can combine slices with individual indices:

``````>>> np.delete(a,(np.r_[0:5,7,9]))
array([5, 6, 8])
``````

However, the deletion is not `in place`, so you have to assign to it.

``````lst = ['a', 'b', 'c', 'd', 'e', 'f', 'g'];
lst = lst[0:2] + lst[6:]
``````

This is a single step operation. It does not use a loop and therefore executes fast. It uses list slicing.

• You should include explanation for your code. In general, describing how and why certain commands or code solves a problem is more useful as it helps the OP and others to solve similar issues.
• 2
• please review the edition and kindly instruct.
• wondering why 1460 days and 23410 views , did not come up with this simple solution. thats kind of depressing.
• 2
• I've edited your answer to improve grammar and to use `lst` for variable name as `list` is a Python data type. The reason why nobody suggested this as a solution is that this creates a new list object (based on the contents of the original) rather than actually modifying the original list object. Since the end result is similar, I'll upvote your answer. Welcome to Stack Exchange.
• 2
• What does [6:] do?

another option (in place, any combination of indices):

``````_marker = object()

for i in indices:
my_list[i] = _marker  # marked for deletion

obj[:] = [v for v in my_list if v is not _marker]
``````

Old question, but I have an answer.

First, peruse the elements of the list like so:

``````for x in range(len(yourlist)):
print '%s: %s' % (x, yourlist[x])
``````

Then, call this function with a list of the indexes of elements you want to pop. It's robust enough that the order of the list doesn't matter.

``````def multipop(yourlist, itemstopop):
result = []
itemstopop.sort()
itemstopop = itemstopop[::-1]
for x in itemstopop:
result.append(yourlist.pop(x))
return result
``````

As a bonus, result should only contain elements you wanted to remove.

In [73]: mylist = ['a','b','c','d','charles']

In [76]: for x in range(len(mylist)):

``````      mylist[x])
``````

....:

0: a

1: b

2: c

3: d

4: charles

...

In [77]: multipop(mylist, [0, 2, 4])

Out[77]: ['charles', 'c', 'a']

...

In [78]: mylist

Out[78]: ['b', 'd']