Remove elements from a List while iterating in Python

avatar
Borislav Hadzhiev

Last updated: Apr 9, 2024
6 min

banner

# Table of Contents

  1. Remove elements from a List while iterating in Python
  2. Remove items from a List while iterating using a list comprehension
  3. Remove items from a List while iterating using filter()
  4. Removing items from a List while iterating over it with range()
  5. Removing items from a list while iterating with filterfalse()

# Remove elements from a List while iterating in Python

To remove list elements while iterating over it:

  1. Use a for loop to iterate over a copy of the list.
  2. Check if each item meets a condition.
  3. Use the list.remove() method to remove the items that meet the condition.
main.py
my_list = [22, 33, 66, 77, 99] for item in my_list.copy(): if item < 50: my_list.remove(item) print(my_list) # ๐Ÿ‘‰๏ธ [66, 77, 99]

remove elements from list while iterating

The code for this article is available on GitHub

We used the list.copy() method to get a copy of the list.

main.py
my_list = [22, 33, 66, 77, 99] print(my_list.copy()) # ๐Ÿ‘‰๏ธ [22, 33, 66, 77, 99]

The list.copy() method returns a shallow copy of the object on which the method was called.

This is necessary because we aren't allowed to remove items from a list while iterating over it.

However, we can iterate over a copy of the list and remove items from the original list.

main.py
my_list = [22, 33, 66, 77, 99] for item in my_list.copy(): if item < 50: my_list.remove(item) print(my_list) # ๐Ÿ‘‰๏ธ [66, 77, 99]

On each iteration in the for loop, we check if the current item is less than 50 and remove the elements that meet the condition.

# Using list slicing to get a shallow copy

You might also see examples that use the my_list[:] syntax to get a shallow copy of the list by using list slicing.

main.py
my_list = [22, 33, 66, 77, 99] for item in my_list[:]: if item < 50: my_list.remove(item) print(my_list) # ๐Ÿ‘‰๏ธ [66, 77, 99]

using list slicing to get shallow copy

The code for this article is available on GitHub

We used the my_list[:] syntax to get a slice that represents the entire list.

main.py
my_list = [22, 33, 66, 77, 99] print(my_list[:]) # ๐Ÿ‘‰๏ธ [22, 33, 66, 77, 99]
This approach achieves the same result as using the list.copy() method, it creates a shallow copy of the list that we can iterate over.

In general, the list.copy() method is a little more readable than using a slice that represents the entire list.

Here is another example.

main.py
my_list = [None, 22, 33, None, 66, 77, None, 99] for item in my_list.copy(): if item is None: my_list.remove(item) print(my_list) # ๐Ÿ‘‰๏ธ [22, 33, 66, 77, 99]

We used a for loop to remove all None values from a list while iterating over it.

The most important thing to note when removing items from a list in a for loop is to use the list.copy() method to iterate over a copy of the list.

If you try to iterate over the original list and remove items from it, you might run into difficult-to-locate bugs.

# You don't have to create a copy if you aren't changing the list's length

If you aren't removing or adding new items to the list when iterating over it, you don't have to create a copy.

main.py
my_list = [5, 11, 25, 7, 30] for index, item in enumerate(my_list): if item <= 10: my_list[index] = 10 print(my_list) # ๐Ÿ‘‰๏ธ [10, 11, 25, 10, 30]

not creating copy if not changing lists length

The code for this article is available on GitHub

We used the enumerate() function to get access to the index of the current iteration.

The enumerate() function takes an iterable and returns an enumerate object containing tuples where the first element is the index and the second is the item.

The example checks if the current list item is less than or equal to 10 and if the condition is met, the item gets set to 10.

We aren't removing or adding items to the list while iterating, so creating a copy isn't necessary.

# Remove items from a List while iterating using a list comprehension

Alternatively, you can use a list comprehension.

The list comprehension will return a new list containing only the elements that match the condition.

main.py
my_list = [77, 105, 123, 88, 199] new_list = [item for item in my_list if item > 100] print(new_list) # ๐Ÿ‘‰๏ธ [105, 123, 199]

remove items from list while iterating with list comprehension

The code for this article is available on GitHub

We used a list comprehension to remove the items from a list while iterating.

List comprehensions are used to perform some operation for every element or select a subset of elements that meet a condition.

On each iteration, we check if the current item is greater than 100 and return the result.

The new list will only contain values that are greater than 100.

The list comprehension in the example doesn't mutate the original list.

# Removing the items from the original list with a list comprehension

If you need to mutate the original list, assign the result to a slice that represents the entire list.

You can update the list in place by using a slice assignment.

main.py
my_list = [77, 105, 123, 88, 199] my_list[:] = [item for item in my_list if item > 100] print(my_list) # ๐Ÿ‘‰๏ธ [105, 123, 199]

We used the my_list[:] syntax to get a slice that represents the entire list, so we can assign to the variable directly.

main.py
my_list = [77, 105, 123, 88, 199] print(my_list[:]) # ๐Ÿ‘‰๏ธ [77, 105, 123, 88, 199]
The code for this article is available on GitHub

The slice my_list[:] represents the entire list, so when we use it on the left-hand side, we are assigning to the entire list.

This approach changes the contents of the original list.

# Remove items from a List while iterating using filter()

You can also use the filter() function to remove items from a list while iterating.

main.py
my_list = [77, 105, 123, 88, 199] new_list = list(filter( lambda x: x > 100, my_list )) print(new_list) # ๐Ÿ‘‰๏ธ [105, 123, 199]

The filter() function takes a function and an iterable as arguments and constructs an iterator from the elements of the iterable for which the function returns a truthy value.

The lambda function we passed to filter gets called with each element of the list.

On each iteration, we check if the current item is greater than 100 and return the result.

The filter object only contains the elements for which the condition is met.

The last step is to convert the filter object to a list using the list() class.

# Removing items from a List while iterating over it with range()

You can also use the range() class to remove items from a list while iterating over it.

main.py
my_list = [77, 105, 123, 88, 199, 4, 1, 5] for index in range(len(my_list) - 1, -1, -1): print(index) if my_list[index] < 100: my_list.pop(index) # ๐Ÿ‘‡๏ธ [105, 123, 199] print(my_list)
The code for this article is available on GitHub

The range() class is commonly used for looping a specific number of times in for loops and takes the following arguments:

NameDescription
startAn integer representing the start of the range (defaults to 0)
stopGo up to, but not including the provided integer
stepRange will consist of every N numbers from start to stop (defaults to 1)

We used a negative step to reverse the range.

main.py
my_list = [77, 105, 123, 88, 199, 4, 1, 5] # ๐Ÿ‘‡๏ธ [7, 6, 5, 4, 3, 2, 1, 0] print(list(range(len(my_list) - 1, -1, -1)))

The range object is not dependent on the list in any way, so removing items from the list doesn't influence the number of iterations.

# Removing items from a list while iterating with filterfalse()

You can also use the filterfalse method from the itertools module to remove items from the list while iterating over it.

main.py
from itertools import filterfalse my_list = [77, 105, 123, 88, 199, 4, 1, 5] def check_func(num): return num < 100 my_list[:] = filterfalse(check_func, my_list) print(my_list) # ๐Ÿ‘‰๏ธ [105, 123, 199]
The code for this article is available on GitHub

Make sure to import the filterfalse method as shown in the code sample.

The filterfalse method takes a predicate and an iterable and calls the function with each item in the iterable.

The method returns a list containing the items for which the function returned false.

In the example, the method returns a list containing the items that are not less than 100.

Which approach you pick is a matter of personal preference. I'd use a for loop with list.copy() because I find it quite direct and intuitive.

# Additional Resources

You can learn more about the related topics by checking out the following tutorials:

I wrote a book in which I share everything I know about how to become a better, more efficient programmer.
book cover
You can use the search field on my Home Page to filter through all of my articles.

Copyright ยฉ 2024 Borislav Hadzhiev