list manipulation
iteration techniques
python programming
loop removal
coding tips

How to remove items from a list while iterating?

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

Introduction

Removing items from a list while iterating over it can produce skipped elements or incorrect behavior because indices shift during mutation. This is a classic bug in Python and many other languages. Safe patterns include building a new list, iterating over a copy, or iterating backwards when in-place removal is required.

Why Direct Removal Fails

Example of problematic pattern:

python
1nums = [1, 2, 3, 4, 5, 6]
2for n in nums:
3    if n % 2 == 0:
4        nums.remove(n)
5print(nums)

Result may be unexpected because list contents move left while iterator index moves forward.

Preferred Pattern: List Comprehension

Create filtered list in one expression.

python
nums = [1, 2, 3, 4, 5, 6]
nums = [n for n in nums if n % 2 != 0]
print(nums)  # [1, 3, 5]

This is clear, fast, and usually best for readability.

In-Place Update Without New Object

If references to original list must remain valid:

python
nums = [1, 2, 3, 4, 5, 6]
nums[:] = [n for n in nums if n % 2 != 0]
print(nums)

Slice assignment mutates existing list object in place.

Iterating Over a Copy

If you prefer explicit remove operations:

python
1nums = [1, 2, 3, 4, 5, 6]
2for n in nums[:]:
3    if n % 2 == 0:
4        nums.remove(n)
5print(nums)

This works because iteration uses snapshot copy.

Reverse Index Iteration

When index operations are needed, iterate backwards.

python
1nums = [1, 2, 3, 4, 5, 6]
2for i in range(len(nums) - 1, -1, -1):
3    if nums[i] % 2 == 0:
4        del nums[i]
5print(nums)

Backward traversal avoids index shift problems.

Filtering Complex Objects

Pattern applies to object lists too.

python
1users = [
2    {"name": "A", "active": True},
3    {"name": "B", "active": False},
4]
5active_users = [u for u in users if u["active"]]
6print(active_users)

For large pipelines, generator expressions can reduce intermediate allocations.

Performance Notes

  • list comprehension is often fastest and clearest
  • repeated .remove inside loop can be costly
  • in-place mutation may be necessary for shared references

Choose based on semantics first, micro performance second.

Removing While Iterating in Other Languages

The same hazard appears in JavaScript and Java collections. The root issue is modifying structure while traversal cursor assumes stable layout.

Stable In-Place Partition Pattern

For performance-sensitive lists, two-pointer partition can avoid repeated removes.

python
1def keep_positive(nums):
2    w = 0
3    for r in range(len(nums)):
4        if nums[r] > 0:
5            nums[w] = nums[r]
6            w += 1
7    del nums[w:]
8
9arr = [3, -1, 2, -5, 7]
10keep_positive(arr)
11print(arr)

This mutates in place with linear complexity and no extra list allocation beyond existing storage.

Choose one standard removal pattern for your codebase and document it in style guides.

Document this pattern for team consistency.

Validate with realistic test cases before deployment.

Common Pitfalls

  • Removing from list while iterating same list directly.
  • Confusing in-place mutation with reassignment semantics.
  • Using .remove when duplicate values require index-aware deletion.
  • Writing complex mutation loops where simple filtering is enough.
  • Ignoring readability in favor of clever but fragile loop logic.

Summary

  • Direct removal during iteration is unsafe due to index shifting.
  • Prefer list comprehensions for most filtering tasks.
  • Use slice assignment for in-place updates when needed.
  • Backward index iteration is safe for in-place deletes.
  • Pick the clearest pattern that matches mutation requirements.

Related reading
Course
Intermediate
27 lessons
15 hours
DSA Fundamentals

Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

All Rights Reserved.