PHP
Array Combinations
Unique Combinations
Programming
Coding Tutorial

PHP Find All somewhat Unique Combinations of an Array

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

Introduction

Generating combinations means selecting items without caring about order. In other words, [1, 2] and [2, 1] represent the same combination. In PHP, the cleanest solution is usually a recursive function that moves forward through the array so it never revisits earlier positions.

Fixed-Length Combinations

A standard recursive approach builds one partial combination at a time and advances the starting index after each choice. That prevents permutations of the same values from being produced.

php
1<?php
2
3function combinations(array $items, int $length, int $start = 0, array $prefix = []): array
4{
5    if ($length === 0) {
6        return [$prefix];
7    }
8
9    $result = [];
10    $max = count($items) - $length;
11
12    for ($i = $start; $i <= $max; $i++) {
13        $nextPrefix = $prefix;
14        $nextPrefix[] = $items[$i];
15        $result = array_merge(
16            $result,
17            combinations($items, $length - 1, $i + 1, $nextPrefix)
18        );
19    }
20
21    return $result;
22}
23
24print_r(combinations([1, 2, 3, 4], 2));

The output contains each pair once:

php
1Array
2(
3    [0] => Array ( [0] => 1 [1] => 2 )
4    [1] => Array ( [0] => 1 [1] => 3 )
5    [2] => Array ( [0] => 1 [1] => 4 )
6    [3] => Array ( [0] => 2 [1] => 3 )
7    [4] => Array ( [0] => 2 [1] => 4 )
8    [5] => Array ( [0] => 3 [1] => 4 )
9)

The key idea is that after choosing index i, the recursion continues from i + 1, never from the beginning.

Generating All Combination Lengths

Sometimes you want every non-empty combination, not just one length. Build that by calling the fixed-length function repeatedly.

php
1<?php
2
3function allCombinations(array $items): array
4{
5    $result = [];
6    for ($length = 1; $length <= count($items); $length++) {
7        $result = array_merge($result, combinations($items, $length));
8    }
9    return $result;
10}
11
12print_r(allCombinations(['A', 'B', 'C']));

That returns single-item, two-item, and three-item combinations while still ignoring order.

Handling Duplicate Values in the Input

The phrase “somewhat unique” often means the input array itself may contain duplicates. In that case, the basic recursion avoids permutation duplicates, but it can still emit repeated value combinations because identical elements at different indices are treated as separate choices.

For example, input [1, 1, 2] can produce duplicate [1, 2] combinations unless you deduplicate deliberately.

A simple method is to sort the array and skip repeated values at the same recursion depth.

php
1<?php
2
3function uniqueCombinations(array $items, int $length, int $start = 0, array $prefix = []): array
4{
5    sort($items);
6    return uniqueCombinationsSorted($items, $length, $start, $prefix);
7}
8
9function uniqueCombinationsSorted(array $items, int $length, int $start, array $prefix): array
10{
11    if ($length === 0) {
12        return [$prefix];
13    }
14
15    $result = [];
16    $count = count($items);
17
18    for ($i = $start; $i < $count; $i++) {
19        if ($i > $start && $items[$i] === $items[$i - 1]) {
20            continue;
21        }
22
23        $nextPrefix = $prefix;
24        $nextPrefix[] = $items[$i];
25        $result = array_merge(
26            $result,
27            uniqueCombinationsSorted($items, $length - 1, $i + 1, $nextPrefix)
28        );
29    }
30
31    return $result;
32}
33
34print_r(uniqueCombinations([1, 1, 2, 3], 2));

Sorting once outside the recursion would be more efficient, but this version keeps the main idea visible.

Complexity and Practical Limits

Combination generation grows quickly. For an array of length n, the number of k-combinations is “n choose k”. That means output size becomes the main cost. If you ask for all combinations of a 20-element array, the result can be very large regardless of implementation details.

When result size matters, consider streaming combinations one at a time with a generator instead of storing them all in memory.

Common Pitfalls

A common mistake is using nested loops tailored to one specific length, such as pairs or triplets. That works only for fixed sizes and becomes unmaintainable fast.

Another issue is confusing combinations with permutations. If order should not matter, the recursion must move forward through the array instead of restarting from index 0.

When the input contains duplicate values, developers often think their algorithm is wrong because repeated combinations appear. The real problem is that duplicate indices still count as distinct choices unless you skip equal values deliberately.

Summary

  • Use recursive forward indexing to generate combinations without permutation duplicates.
  • Build fixed-length combinations first, then compose all lengths if needed.
  • Duplicate values in the input require extra deduplication logic.
  • Combination counts grow quickly, so output size becomes the main cost.
  • For large inputs, consider generators instead of storing every result at once.

Related reading
Course
Intermediate
27 lessons
15 hours
DSA Fundamentals

Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

All Rights Reserved.