partition
Splits an array into two subarrays based on a predicate function. The first array contains items that match the predicate, and the second contains those that do not.
1/**
2 * Splits an array into two subarrays based on a predicate function.
3 * The first array contains items that match the predicate,
4 * and the second contains those that do not.
5 *
6 * @param arr - The input array.
7 * @param fn - A predicate function to test each element.
8 * @returns A tuple of two arrays: [matched, unmatched].
9 */
10export function partition<T>(arr: T[], fn: (item: T) => boolean): [T[], T[]] {
11 return arr.reduce<[T[], T[]]>(
12 (acc, item) => {
13 acc[fn(item) ? 0 : 1].push(item);
14 return acc;
15 },
16 [[], []]
17 );
18}
Efficient single-pass implementation
Uses
Array.prototype.reduce
to evaluate and split elements in just one traversal.Immutability
Does not mutate the original array, ensuring functional safety and predictability.
Clean and minimal logic
Avoids verbose control flow — condenses logic into a short, expressive structure using ternary access.
Generic and type-safe
Fully supports generic types, maintaining strong TypeScript type inference and safety.
Universally applicable
Works with arrays of any type and any boolean-returning condition function.
Tests | Examples
1test('partition - even and odd numbers', () => {
2 expect(partition([1, 2, 3, 4], n => n % 2 === 0)).toEqual([[2, 4], [1, 3]]);
3});
4
5test('partition - all true', () => {
6 expect(partition(['a', 'b'], () => true)).toEqual([['a', 'b'], []]);
7});
8
9test('partition - all false', () => {
10 expect(partition(['a', 'b'], () => false)).toEqual([[], ['a', 'b']]);
11});
12
13test('partition - empty array', () => {
14 expect(partition([], () => true)).toEqual([[], []]);
15});
16
17test('partition - complex predicate', () => {
18 const users = [
19 { name: 'Alice', active: true },
20 { name: 'Bob', active: false },
21 ];
22 expect(partition(users, u => u.active)).toEqual([
23 [{ name: 'Alice', active: true }],
24 [{ name: 'Bob', active: false }],
25 ]);
26});
Common Use Cases
Filtering while preserving both outcomes
Instead of filtering twice (once for matching and once for non-matching), you get both subsets at once.
Form validation
Split fields or entries into valid and invalid groups based on custom criteria.
Log or data classification
Separate log entries, analytics events, or items into handled/unhandled, critical/non-critical, etc.
Business logic decisions
Group objects like orders, tasks, or items into active/inactive, processed/pending, allowed/denied, etc.
Performance optimization
Reduces the need for multiple passes over the array and avoids redundant condition checks.