A Better Way to Divide Laravel Collections: Meet partition()

A Better Way to Divide Laravel Collections: Meet partition()

Splitting up a dataset into two different sets based on some specific condition is a common programming task. Like separating active users from inactive users or paid invoices from the ones that are overdue or passed tests from the failed ones.

The way we usually do this is by calling filter() or map() twice with inverse logic or run a foreach loop with two empty arrays to push the results to. Laravel Collections provide a much cleaner solution to this problem called partition().

The Repetitive Double filter() Way

When developers need two groups, they often write code like this:

$orders = Order::all();

// Iterates through the collection TWICE
$completedOrders = $orders->filter(fn ($order) => $order->isCompleted());
$pendingOrders   = $orders->filter(fn ($order) => !$order->isCompleted());

This approach forces PHP to loop through the entire list twice and duplicates the conditional logic with an inverted ! check.

The Cleaner Way: partition()

The partition() method divides the collection into two separate collections during a single pass, where the first is formed from elements that passed the truth test and the second consists of elements that did not.

$orders = Order::all();

$partitioned = $orders->partition(function ($order) {
    return $order->isCompleted();
});

// $partitioned[0] contains completed orders
// $partitioned[1] contains remaining (pending/cancelled) orders

Using Array Destructuring

Instead of referencing $partitioned[0] and $partitioned[1], we can simply pair partition() also with PHP array destructuring for clean, readable variable assignments.

[$paidInvoices, $unpaidInvoices] = $invoices->partition(function ($invoice) {
    return $invoice->isPaid();
});

// Process each group independently
$paidInvoices->each->archive();
$unpaidInvoices->each->sendReminder();

// Any other operations here.

Higher-Order Partitioning

If your condition relies on a model method or property, you can make it even shorter using Laravel's Higher-Order Messaging:

// Calling a boolean method via higher-order proxy
[$activeUsers, $inactiveUsers] = $users->partition->isActive();
// Or evaluating a boolean property directly [$verified, $unverified] = $users->partition->email_verified;

This single line replaces multiple filter calls and makes the business logic easy to understand and readable.

Summary

Approach Passes Over Data Readability
filter() + filter(!...) 2 iterations Repetitive logic with inverted checks.
partition() 1 single pass Clean destructuring into two named variables.

When we need to split a collection into two groups, where each element has to meet a true/false condition, avoid calling filter() twice, instead use partition() to do that in one pass, which you can then destructure into two arrays.

Thank you for reading this article 😊

For any query, do not hesitate to comment 💬


Previous Post Next Post

Contact Form