Explain Codes LogoExplain Codes Logo

How can I partition (split up, divide) a list based on a condition?

python
partition
list
comprehension
Anton ShumikhinbyAnton Shumikhin·Feb 10, 2025
TLDR

You can quickly partition a list into two distinct lists using list comprehensions. These lists are divided based on whether elements satisfy a condition or not:

my_list = [1, 2, 3, 4] even, odd = [x for x in my_list if x % 2 == 0], [x for x in my_list if x % 2 != 0]

Here, even will comprise all even numbers, while odd will encase all the odd numbers from my_list, neatly divided like team captains pick players for a schoolyard match.

Advanced partition strategies

Single-pass loop

The earlier list comprehension is short and clean, but let's slice the list only once using a for loop to sort each element into the correct list. Here's how you do it:

my_list = [1, 2, 3, 4] even, odd = [], [] # The two team "captains" are ready for x in my_list: (even if x % 2 == 0 else odd).append(x)

This one-pass maneuver ensures we're not taking an extra lap around the list, saving us some precious milliseconds when working with large datasets.

Using filter function

Personalize your partitioning criteria with the filter function. Combine it with lambda expressions or custom functions to achieve separate collections:

my_list = range(100) # Be gentle with those 3s; they have feelings too three_ok, three_no = list(filter(lambda x: x % 3 == 0, my_list)), list(filter(lambda x: x % 3 != 0, my_list))

Crafting custom cutter functions

Craft a custom function to partition on demand. It spares you the headache of rewriting the same logic repeatedly:

def partition(cond, seq): return ([x for x in seq if cond(x)], [x for x in seq if not cond(x)]) my_list = range(100) under_five, over_or_equal_five = partition(lambda x: x < 5, my_list)

Slice it on the run with lazy generators

Working with unlimited or rock-sized lists? Use generators. They delay computations until you require the results, radically saving on memory:

def lazy_partition(cond, seq): # Generators keeping our memory footprint light a = (x for x in seq if cond(x)) b = (x for x in seq if not cond(x)) return a, b my_list = iter(range(100)) under_fifty, over_or_equal_fifty = lazy_partition(lambda x: x < 50, my_list)

Respecting order and performance

Order-obsessed slicing

If the element order inside your list is vital, combine loops with collections.deque for rapid appends

from collections import deque my_list = ['apple', 'banana', 'cherry', 'date'] sweet, other = deque(), deque() # Every fruit finds its place in the rightful basket for fruit in my_list: (sweet if fruit.startswith('a') else other).append(fruit) sweet = list(sweet) other = list(other)

Performance-chasing partition

When performance becomes an issue, you may modify element selection methods or create a getNext() method in a custom SplitSeq class. Remember, running fast is good, but knowing when and where to run is the art of winning.

Crafting a function Picasso would use

Create generic functions that can chop up any list based on multiple partition scenarios. They become a Swiss army knife you would continue to reuse:

def flexible_partition(seq, *conds): results = [[] for _ in conds] for item in seq: for i, cond in enumerate(conds): if cond(item): results[i].append(item) break return results

Now, run it:

my_list = range(10) under_five, multiples_of_two, no_match = flexible_partition( my_list, lambda x: x < 5, lambda x: x % 2 == 0 ) # Voila: pieces of the list, chopped to serve your purpose

The right tool for the partition job

Choosing the best partitioning method hinges on what your particular needs are. Highlighting the importance of performance, but also the power of order preservation and efficient memory management. In complex cases, the python-split library has ready-to-use tools, such as lazy partitioning for handling more demanding partitioning tasks.

Elegance in code is not an accessory

Balancing performance enhancement with readable and elegant code is vital. It's easier to understand, modify, and integrate, and there are no cruel surprises hiding in the lines. Choosing between microscopic time gains versus comprehensible code is a choice eventually guided by our partitioning method.