Code Snippets
/

Partition an Array by a Predicate

Partition an Array by a Predicate

Calling `array.filter(p)` and `array.filter((x) => !p(x))` works but walks the input twice and runs the predicate twice per element, which is wasteful and (for non-pure predicates) plain wrong. A single-pass `partition` returns the matched and unmatched buckets in one go. This snippet covers a clean fold-based implementation, an N-way `partitionBy` for multi-class splits, and a streaming variant that lazily partitions an iterable without materialising the full input.

JavaScript
Medium
4 snippets
arrays
utility
array-manipulation-patterns
functional-programming

758 views

18

function partition(array, predicate) {
    const pass = [];
    const fail = [];
    for (let i = 0; i < array.length; i++) {
        const item = array[i];
        if (predicate(item, i, array)) {
            pass.push(item);
        } else {
            fail.push(item);
        }
    }
    return [pass, fail];
}

const numbers = [1, 2, 3, 4, 5, 6];
const [evens, odds] = partition(numbers, (n) => n % 2 === 0);
console.log(evens); // [2, 4, 6]
console.log(odds);  // [1, 3, 5]

const users = [
    { name: 'Ada', active: true },
    { name: 'Bo', active: false },
    { name: 'Cal', active: true },
];
const [active, inactive] = partition(users, (u) => u.active);
console.log(active.length, inactive.length); // 2 1

A classic for loop runs the predicate exactly once per element and pushes into one of two buckets. Returning a tuple [pass, fail] lets the caller destructure cleanly: const [yes, no] = partition(...). Compared to [arr.filter(p), arr.filter(notP)], this version is twice as fast on large inputs and correct even when the predicate is impure (e.g. randomised, time-based, or one that mutates a counter). The third predicate argument matches the Array.prototype.filter contract (item, index, array), so any predicate that works with filter is a drop-in here.