Python
indexing
lists
programming
tutorial

In Python, how do I index a list with another list?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Python lists do not support "fancy indexing" the same way NumPy arrays do, so you cannot write items[[0, 2, 4]] and expect a subset back. The usual Python approach is to loop over the index list and build a new result list explicitly.

Why Direct List-of-Indexes Access Fails

The list subscription operator expects a single integer or a slice. When you pass another list, Python raises a TypeError because a plain list does not know how to interpret multiple positions at once.

python
1items = ["apple", "banana", "cherry", "date", "elderberry"]
2positions = [0, 2, 4]
3
4try:
5    print(items[positions])
6except TypeError as exc:
7    print(exc)

The result is an error similar to "list indices must be integers or slices, not list". That message is the signal that you need a different pattern.

Use a List Comprehension

The most common solution is a list comprehension. It is readable, fast enough for most code, and works with any iterable of indexes.

python
1items = ["apple", "banana", "cherry", "date", "elderberry"]
2positions = [0, 2, 4]
3
4selected = [items[i] for i in positions]
5print(selected)
text
['apple', 'cherry', 'elderberry']

This works because the comprehension evaluates items[i] once for each value in positions and collects the results into a new list. If your index list contains duplicates, they are preserved in the output.

python
1items = ["a", "b", "c"]
2positions = [2, 2, 0]
3
4print([items[i] for i in positions])
text
['c', 'c', 'a']

That behavior is often useful when the second list is not just a filter, but an explicit ordering rule.

Validate Indexes When Input Is Untrusted

If the indexes come from a file, a user, or another system, validate them before indexing. Otherwise a single invalid position can raise IndexError.

python
1items = ["apple", "banana", "cherry"]
2positions = [0, 5, 1]
3
4safe_selected = [items[i] for i in positions if -len(items) <= i < len(items)]
5print(safe_selected)
text
['apple', 'banana']

The range check keeps valid positive and negative indexes. Negative indexes are legal in Python, so -1 means the last element, -2 means the second-to-last element, and so on.

If you want invalid indexes to fail loudly instead of being skipped, leave out the condition and let Python raise the exception. That is usually better in business logic where silent data loss would be worse than a crash.

Alternative: operator.itemgetter

When you want a compact functional style, operator.itemgetter can pull multiple positions at once. It returns a tuple when you ask for more than one item.

python
1from operator import itemgetter
2
3items = ["apple", "banana", "cherry", "date", "elderberry"]
4getter = itemgetter(0, 2, 4)
5
6selected = getter(items)
7print(selected)
8print(type(selected))
text
('apple', 'cherry', 'elderberry')
<class 'tuple'>

This can be convenient when the indexes are fixed and known ahead of time. It is less flexible if the index list is dynamic, because you typically need to unpack it first.

python
1from operator import itemgetter
2
3items = ["apple", "banana", "cherry", "date"]
4positions = [1, 3]
5
6selected = itemgetter(*positions)(items)
7print(list(selected))

When a NumPy Array Is a Better Fit

If you do this kind of indexing heavily in numeric or data-processing code, a NumPy array may be the right structure. NumPy supports advanced indexing directly.

python
1import numpy as np
2
3items = np.array(["apple", "banana", "cherry", "date", "elderberry"])
4positions = [0, 2, 4]
5
6print(items[positions])
text
['apple' 'cherry' 'elderberry']

That does not mean you should convert every list to NumPy. For small general-purpose programs, a comprehension is simpler and avoids an extra dependency. NumPy becomes attractive when the surrounding code is already array-based.

Common Pitfalls

One common mistake is expecting my_list[indexes] to work on a built-in list. That syntax only works on types that implement multi-index behavior, such as NumPy arrays.

Another issue is forgetting that negative indexes are valid. If you write validation code that only allows zero through len(items) - 1, you may accidentally reject legitimate positions like -1.

A third problem is hiding bad data by filtering too aggressively. Skipping invalid indexes is fine for exploratory scripts, but in production code it can mask upstream bugs. Decide whether your function should fail fast or recover, and make that behavior explicit.

Summary

  • Plain Python lists accept a single index or a slice, not a list of indexes.
  • The standard solution is a list comprehension such as [items[i] for i in positions].
  • Validate indexes when they come from untrusted input, especially if out-of-range values are possible.
  • 'operator.itemgetter is useful for fixed-position extraction and returns a tuple.'
  • NumPy arrays support advanced indexing directly and are a better fit for array-heavy workflows.

Course illustration
Course illustration

All Rights Reserved.