How to remove an element from a list by index

Asked 2023-09-20 20:54:14 View 773,128

How do I remove an element from a list by index?

I found list.remove(), but this slowly scans the list for an item by value.

  • @smci: Python list is array-based: to delete an item in the middle, you have to move all items on the right to remove the gap that is why it is O(n) in time operation. deque() provides efficient operations on both ends but it does not provide O(1) insertions/lookups/deletions in the middle. - anyone
  • @J.F.Sebastian: cPython implementation, yes, thanks for correcting me. Strictly the language spec doesn't specify how to implement list, alternative implementations could choose to use a linked-list. - anyone
  • @smci: no practical Python implementation would use O(n) index access a[i] (due to linked-lists). Note: array-based implementation provides O(1) index access. - anyone
  • @J.F.Sebastian: of course. I merely noted that the language spec does not define this, it's an implementation issue. (I was surprised to find that it didn't.) - anyone
  • @NickT: I'm merely cautioning to distinguish when something is implementation-defined due to not being defined in the language spec. It was exactly that sort of assumption that caused major grief with hash instability (between platforms) back in 2.x. Obviously most rational implementations of Python's list would never choose linked-list since we want the basic operations to be O(1). That's all. - anyone

Answers

Use del and specify the index of the element you want to delete:

>>> a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> del a[-1]
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8]

Also supports slices:

>>> del a[2:4]
>>> a
[0, 1, 4, 5, 6, 7, 8, 9]

Here is the section from the tutorial.

Answered   2023-09-20 20:54:14

  • Thanks, what's the difference between pop and del? - anyone
  • del is overloaded. For example del a deletes the whole list - anyone
  • another example del a[2:4], deletes elements 2 and 3 - anyone
  • pop() returns the element you want to remove. del just deletes is. - anyone
  • I cannot see a proof of "linked list" there. Look at svn.python.org/projects/python/trunk/Objects/listobject.c how PyList_GetItem() essentially returns ((PyListObject *)op) -> ob_item[i]; - the ith element of an array. - anyone

You probably want pop:

a = ['a', 'b', 'c', 'd']
a.pop(1)

# now a is ['a', 'c', 'd']

By default, pop without any arguments removes the last item:

a = ['a', 'b', 'c', 'd']
a.pop()

# now a is ['a', 'b', 'c']

Answered   2023-09-20 20:54:14

  • By the way, pop() returns whatever element it removed. - anyone
  • @S.Lott: It uses the end by default because it's O(1) there; it's O(n) at the beginning. - anyone
  • This answer is incorrect. pop() returns the value removed from the array, not the array without the value you wanted to remove as shown in the code's comments. I believe that it doesn't answer the original question, as it was not asked how to extract a value from an array but to remove it. - anyone
  • @Seb, You're correct in that it returns the value you delete, but there's no requirement in the question saying the list had to be regenerated or returned. Since pop mutates the list in place, it fulfills the requirements set forth by the question exactly, albeit with a superfluous return value. I'd even argue that pop is more correct than the accepted answer, since del is a keyword that's linked pretty closely to the memory management of the running program, compared to list.pop, which is a feature of the list object in Python. - anyone
  • in summary, do I use del or pop to modify and delete that element with no weird errors? - anyone

Like others mentioned pop and del are the efficient ways to remove an item of given index. Yet just for the sake of completion (since the same thing can be done via many ways in Python):

Using slices (this does not do in place removal of item from original list):

(Also this will be the least efficient method when working with Python list, but this could be useful (but not efficient, I reiterate) when working with user defined objects that do not support pop, yet do define a __getitem__ ):

>>> a = [1, 2, 3, 4, 5, 6]
>>> index = 3 # Only positive index

>>> a = a[:index] + a[index+1 :]
# a is now [1, 2, 3, 5, 6]

Note: Please note that this method does not modify the list in place like pop and del. It instead makes two copies of lists (one from the start until the index but without it (a[:index]) and one after the index till the last element (a[index+1:])) and creates a new list object by adding both. This is then reassigned to the list variable (a). The old list object is hence dereferenced and hence garbage collected (provided the original list object is not referenced by any variable other than a).

This makes this method very inefficient and it can also produce undesirable side effects (especially when other variables point to the original list object which remains un-modified).

Thanks to @MarkDickinson for pointing this out ...

This Stack Overflow answer explains the concept of slicing.

Also note that this works only with positive indices.

While using with objects, the __getitem__ method must have been defined and more importantly the __add__ method must have been defined to return an object containing items from both the operands.

In essence, this works with any object whose class definition is like:

class foo(object):
    def __init__(self, items):
        self.items = items

    def __getitem__(self, index):
        return foo(self.items[index])

    def __add__(self, right):
        return foo( self.items + right.items )

This works with list which defines __getitem__ and __add__ methods.

Comparison of the three ways in terms of efficiency:

Assume the following is predefined:

a = range(10)
index = 3

The del object[index] method:

By far the most efficient method. It works will all objects that define a __del__ method.

The disassembly is as follows:

Code:

def del_method():
    global a
    global index
    del a[index]

Disassembly:

 10    0 LOAD_GLOBAL     0 (a)
       3 LOAD_GLOBAL     1 (index)
       6 DELETE_SUBSCR   # This is the line that deletes the item
       7 LOAD_CONST      0 (None)
      10 RETURN_VALUE
None

pop method:

It is less efficient than the del method and is used when you need to get the deleted item.

Code:

def pop_method():
    global a
    global index
    a.pop(index)

Disassembly:

 17     0 LOAD_GLOBAL     0 (a)
        3 LOAD_ATTR       1 (pop)
        6 LOAD_GLOBAL     2 (index)
        9 CALL_FUNCTION   1
       12 POP_TOP
       13 LOAD_CONST      0 (None)
       16 RETURN_VALUE

The slice and add method.

The least efficient.

Code:

def slice_method():
    global a
    global index
    a = a[:index] + a[index+1:]

Disassembly:

 24     0 LOAD_GLOBAL    0 (a)
        3 LOAD_GLOBAL    1 (index)
        6 SLICE+2
        7 LOAD_GLOBAL    0 (a)
       10 LOAD_GLOBAL    1 (index)
       13 LOAD_CONST     1 (1)
       16 BINARY_ADD
       17 SLICE+1
       18 BINARY_ADD
       19 STORE_GLOBAL   0 (a)
       22 LOAD_CONST     0 (None)
       25 RETURN_VALUE
None

Note: In all three disassembles ignore the last two lines which basically are return None. Also the first two lines are loading the global values a and index.

Answered   2023-09-20 20:54:14

  • Your slicing method does not remove an element from a list: instead it creates a new list object containing all but the ith entry from the original list. The original list is left unmodified. - anyone
  • @MarkDickinson Have edited the answer to clarify the same ... Please let me know if it looks good now ? - anyone
  • Maybe the answer wasn't entirely on topic, but the indexing method is useful if you need to omit an item from an immutable object, such as a tuple. pop() and del() will not work in that case. - anyone
  • @rvraghav93 out of all presented methods during the entire post, the a = a[:index] + a[index+1 :]-trick was the savest, when it comes to huge lists. All the other methods ended up in a deadlock. So thank you very much - anyone
  • Indeed Mark, you are grumpy. This answer is the one I prefered because it was really pedagogical. I learned most from this answer and the desassembly details that were provided and the impact on performanc. Plus the slicing method, yes, create another object, but now it is specified and sometimes that is also what you need. - anyone

If you want to remove elements at specific positions in a list, like the 2nd, 3rd and 7th elements, you can't use

del my_list[2]
del my_list[3]
del my_list[7]

Since after you delete the second element, the third element you delete actually is the fourth element in the original list. You can filter the 2nd, 3rd and 7th elements in the original list and get a new list, like below:

new_list = [j for i, j in enumerate(my_list) if i not in [2, 3, 7]]

Answered   2023-09-20 20:54:14

  • Fits my need. I need to go through a list and delete some of them. So with this method I will just save in another list the indexes of the elements I want to remove, and then at the end I will use the method you gave to remove them all at once. - anyone
  • You can still call del repeatedly, as long as you do it from the largest index first, like in nspo's answer. - anyone

pop is also useful to remove and keep an item from a list. Where del actually trashes the item.

>>> x = [1, 2, 3, 4]

>>> p = x.pop(1)
>>> p
    2

Answered   2023-09-20 20:54:14

It has already been mentioned how to remove a single element from a list and which advantages the different methods have. Note, however, that removing multiple elements has some potential for errors:

>>> l = [0,1,2,3,4,5,6,7,8,9]
>>> indices=[3,7]
>>> for i in indices:
...     del l[i]
... 
>>> l
[0, 1, 2, 4, 5, 6, 7, 9]

Elements 3 and 8 (not 3 and 7) of the original list have been removed (as the list was shortened during the loop), which might not have been the intention. If you want to safely remove multiple indices you should instead delete the elements with highest index first, e.g. like this:

>>> l = [0,1,2,3,4,5,6,7,8,9]
>>> indices=[3,7]
>>> for i in sorted(indices, reverse=True):
...     del l[i]
... 
>>> l
[0, 1, 2, 4, 5, 6, 8, 9]

Answered   2023-09-20 20:54:14

Use the del statement:

del listName[-N]

For example, if you want to remove the last 3 items, your code should be:

del listName[-3:]

For example, if you want to remove the last 8 items, your code should be:

del listName[-8:]

Answered   2023-09-20 20:54:14

This depends on what you want to do.

If you want to return the element you removed, use pop():

>>> l = [1, 2, 3, 4, 5]
>>> l.pop(2)
3
>>> l
[1, 2, 4, 5]

However, if you just want to delete an element, use del:

>>> l = [1, 2, 3, 4, 5]
>>> del l[2]
>>> l
[1, 2, 4, 5]

Additionally, del allows you to use slices (e.g. del[2:]).

Answered   2023-09-20 20:54:14

Yet another way to remove an element(s) from a list by index.

a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# remove the element at index 3
a[3:4] = []
# a is now [0, 1, 2, 4, 5, 6, 7, 8, 9]

# remove the elements from index 3 to index 6
a[3:7] = []
# a is now [0, 1, 2, 7, 8, 9]

a[x:y] points to the elements from index x to y-1. When we declare that portion of the list as an empty list ([]), those elements are removed.

Answered   2023-09-20 20:54:14

Generally, I am using the following method:

>>> myList = [10,20,30,40,50]
>>> rmovIndxNo = 3
>>> del myList[rmovIndxNo]
>>> myList
[10, 20, 30, 50]

Answered   2023-09-20 20:54:14

You could just search for the item you want to delete. It is really simple. Example:

    letters = ["a", "b", "c", "d", "e"]
    letters.remove(letters[1])
    print(*letters) # Used with a * to make it unpack you don't have to (Python 3.x or newer)

Output: a c d e

Answered   2023-09-20 20:54:14

  • I like this solution, but of course it assumes your list does not have duplicates. - anyone

Use the following code to remove element from the list:

list = [1, 2, 3, 4]
list.remove(1)
print(list)

output = [2, 3, 4]

If you want to remove index element data from the list use:

list = [1, 2, 3, 4]
list.remove(list[2])
print(list)
output : [1, 2, 4]

Answered   2023-09-20 20:54:14

  • Comes with the caveat that your list cannot contain duplicates. - anyone
  • This is not removing by index, but removing by matching value. That might be valuable information for some people visiting here, but doesn't try to answer OPs question at all. - anyone

As previously mentioned, best practice is del(); or pop() if you need to know the value.

An alternate solution is to re-stack only those elements you want:

    a = ['a', 'b', 'c', 'd'] 

    def remove_element(list_,index_):
        clipboard = []
        for i in range(len(list_)):
            if i is not index_:
                clipboard.append(list_[i])
        return clipboard

    print(remove_element(a,2))

    >> ['a', 'b', 'd']

eta: hmm... will not work on negative index values, will ponder and update

I suppose

if index_<0:index_=len(list_)+index_

would patch it... but suddenly this idea seems very brittle. Interesting thought experiment though. Seems there should be a 'proper' way to do this with append() / list comprehension.

pondering

Answered   2023-09-20 20:54:14

  • Which version of Python has a function del()? For that function you provide the list as the first argument to that function and then the index, or the index first and then the list? Does it return the list argument without the item, or does it do the deleting in place. I know about the del statement, but not about a function with the same name. - anyone

l - list of values; we have to remove indexes from inds2rem list.

l = range(20)
inds2rem = [2,5,1,7]
map(lambda x: l.pop(x), sorted(inds2rem, key = lambda x:-x))

>>> l
[0, 3, 4, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]

Answered   2023-09-20 20:54:14

  • not working, the answer is <map at 0x7f4d54109a58>. and l is range(0,20) - anyone

It doesn't sound like you're working with a list of lists, so I'll keep this short. You want to use pop since it will remove elements not elements that are lists, you should use del for that. To call the last element in python it's "-1"

>>> test = ['item1', 'item2']
>>> test.pop(-1)
'item2'
>>> test
['item1']

Answered   2023-09-20 20:54:14

  • pop() and del both remove an element at the provided index, independent of whether that element is itself a list or not. a = [1, [2, 3], 4]; del a[1]; b = [1, [2, 3], 4]; b.pop(1); assert a == b - anyone

Or if multiple indexes should be removed:

print([v for i,v in enumerate(your_list) if i not in list_of_unwanted_indexes])

Of course then could also do:

print([v for i,v in enumerate(your_list) if i != unwanted_index])

Answered   2023-09-20 20:54:14

  • Why don't you just sort the list of indices in reverse order and then delete them one by one? That way you don't have to make a new list. - anyone

You can use either del or pop to remove element from list based on index. Pop will print member it is removing from list, while list delete that member without printing it.

>>> a=[1,2,3,4,5]
>>> del a[1]
>>> a
[1, 3, 4, 5]
>>> a.pop(1)
 3
>>> a
[1, 4, 5]
>>> 

Answered   2023-09-20 20:54:14

One can either use del or pop, but I prefer del, since you can specify index and slices, giving the user more control over the data.

For example, starting with the list shown, one can remove its last element with del as a slice, and then one can remove the last element from the result using pop.

>>> l = [1,2,3,4,5]
>>> del l[-1:]
>>> l
[1, 2, 3, 4]
>>> l.pop(-1)
4
>>> l
[1, 2, 3]

Answered   2023-09-20 20:54:14