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:
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:
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:
This may be fine, or it may hide a bug. If matching lengths are required, validate them first:
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:
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:
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:
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.compressis 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.

