How to Split a List by a Predicate into Two Lists in Python
Partition any Python list into two lists based on a predicate: items that match go into one list, everything else into the other.
Python code
20 linesfrom typing import Callable, List, TypeVar
T = TypeVar("T")
def split_by_predicate(items: List[T], predicate: Callable[[T], bool]) -> tuple[List[T], List[T]]:
matching = []
non_matching = []
for item in items:
if predicate(item):
matching.append(item)
else:
non_matching.append(item)
return matching, non_matching
if __name__ == "__main__":
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
evens, odds = split_by_predicate(numbers, lambda n: n % 2 == 0)
print(f"Evens: {evens}")
print(f"Odds: {odds}")
Output
Evens: [2, 4, 6, 8, 10]
Odds: [1, 3, 5, 7, 9]
How it works
This function iterates over the input list once and appends each item to either the matching or non_matching list depending on whether predicate(item) returns True. Because it builds two new lists, the original ordering is preserved in each result. The TypeVar and Callable types make the function generic and reusable for any element type. This approach runs in O(n) time with O(n) extra memory for the two output lists.
Common mistakes
- Forgetting to handle the empty list case — the function returns two empty lists, which is usually fine but can surprise callers.
- Mutating the input list inside the loop, which can cause skipped items or infinite loops.
- Returning `(non_matching, matching)` by accident, swapping the order of the output lists.
- Using `filter` and list comprehension separately for each side, leading to two passes instead of one.
Variations
- Use `filter(predicate, items)` and `filter(lambda x: not predicate(x), items)` for a functional one-liner.
- Use `[x for x in items if predicate(x)]` and `[x for x in items if not predicate(x)]` for readability at the cost of double iteration.
Real-world use cases
- Splitting user records into active vs inactive before sending batch email notifications.
- Partitioning log messages into error vs non-error for separate alerting pipelines.
- Categorizing inventory items into in-stock vs backorder at the start of a replenishment job.
Sponsored
More from Algorithms & data structures
- Binary Search for Ship Capacity in Python medium
- Binary Search on Answer in Python: Koko Eating Bananas medium
- Bucket Numbers into Histogram Bin Counts in Python easy
- Container With Most Water: Two-Pointer Solution in Python medium
- Count Smaller Elements to the Right in Python easy
- Depth First Search Traversal Order in Python easy
Keep learning
Related tutorials and quizzes for this topic.