Python
Boolean Logic
List Comprehension
Data Filtering
Programming Tips

Filtering a list based on a list of booleans

Master System Design with Codemia

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

Introduction

Filtering one list by another list of booleans is a masking operation. Each True value means "keep the item at this position," and each False value means "drop it."

The Most Direct Python Solution

In plain Python, the cleanest approach is usually zip plus a list comprehension:

python
1data = ["a", "b", "c", "d"]
2mask = [True, False, True, False]
3
4filtered = [item for item, keep in zip(data, mask) if keep]
5
6print(filtered)  # ['a', 'c']

This works because zip pairs each item with its corresponding boolean flag, and the comprehension keeps only the pairs whose flag is true.

Why This Is the Usual Answer

The zip approach is popular because it is:

  • readable
  • built into Python
  • easy to adapt for more complex conditions

It also makes the positional relationship between data and mask explicit, which is exactly what this problem is about.

itertools.compress Is Another Good Option

Python's standard library also provides a helper that is designed for this exact pattern:

python
1from itertools import compress
2
3data = ["a", "b", "c", "d"]
4mask = [True, False, True, False]
5
6filtered = list(compress(data, mask))
7
8print(filtered)  # ['a', 'c']

compress is nice when you want the intent to read as "apply this mask to this iterable." It is especially tidy in pipelines that already use itertools.

Length Mismatch Behavior

One important detail is that both zip and compress stop at the shorter input. That means:

python
1data = ["a", "b", "c", "d"]
2mask = [True, False]
3
4filtered = [item for item, keep in zip(data, mask) if keep]
5print(filtered)  # ['a']

This may be fine, or it may hide a bug. If matching lengths are required, validate them first:

python
if len(data) != len(mask):
    raise ValueError("data and mask must have the same length")

That small check prevents silent truncation.

NumPy Has Native Boolean Masking

If the data is numeric and already in an array, NumPy offers direct boolean indexing:

python
1import numpy as np
2
3data = np.array([10, 20, 30, 40])
4mask = np.array([True, False, True, False])
5
6filtered = data[mask]
7print(filtered)  # [10 30]

This is often the most efficient and expressive option for numerical workloads, but it applies to arrays rather than ordinary Python lists.

Keep the Mask Semantics Clear

A boolean mask is positional. That means the first boolean applies to the first item, the second boolean to the second item, and so on. It is not a content-based filter by itself.

For example:

python
1data = ["red", "green", "blue"]
2mask = [False, True, True]
3
4print([item for item, keep in zip(data, mask) if keep])

The mask says nothing about the words green or blue directly. It only says "keep positions two and three."

When a Direct Condition Is Better

Sometimes a separate boolean list is unnecessary. If the keep-or-drop rule can be computed directly from the items, a normal condition is clearer:

python
1numbers = [10, 21, 30, 41]
2filtered = [n for n in numbers if n % 2 == 0]
3
4print(filtered)  # [10, 30]

Use a mask when the selection state already exists separately, not just because masks are possible.

Common Pitfalls

The most common mistake is forgetting that zip stops at the shorter iterable. If data and mask lengths differ, items at the end may be ignored silently.

Another issue is using strings like "True" and "False" instead of real booleans. Non-empty strings are truthy in Python, so that can produce very surprising results.

People also reach for NumPy-style syntax on plain Python lists. Boolean indexing like data[mask] is for array libraries, not for normal lists.

Summary

  • The standard Python solution is [item for item, keep in zip(data, mask) if keep].
  • 'itertools.compress is a clean standard-library alternative.'
  • Validate lengths if a mask mismatch should be treated as an error.
  • Use NumPy boolean indexing when you are already working with arrays.
  • A boolean mask is positional, so each flag applies to the item at the same index.

Course illustration
Course illustration

All Rights Reserved.