combinatorics
permutations
algorithms
programming
number combinations

Getting all possible combinations from a list of numbers

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

When people ask for "all possible combinations" of a list, they often mean one of several different things: combinations of a fixed size, all subsets of every size, or permutations where order matters. The first step is to decide which of those results you actually need.

Once that is clear, the implementation is straightforward. In Python, the itertools module already provides efficient generators for the most common variants, so you rarely need to write the combinatorics logic yourself.

Combinations of a Fixed Length

If order does not matter and each element can be used at most once, use itertools.combinations.

python
1from itertools import combinations
2
3numbers = [1, 2, 3, 4]
4
5result = list(combinations(numbers, 2))
6print(result)

Output:

python
[(1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4)]

This returns all unique 2-element combinations. Notice that (1, 2) appears, but (2, 1) does not, because combinations ignore ordering.

Generate All Combination Sizes

If you want every possible non-empty subset, iterate over all valid lengths:

python
1from itertools import combinations
2
3numbers = [1, 2, 3]
4all_combinations = []
5
6for r in range(1, len(numbers) + 1):
7    all_combinations.extend(combinations(numbers, r))
8
9print(all_combinations)

Output:

python
[(1,), (2,), (3,), (1, 2), (1, 3), (2, 3), (1, 2, 3)]

That pattern effectively gives you the power set minus the empty set.

Include the Empty Combination if Needed

In some algorithms, the empty subset is meaningful. If so, start the range at 0:

python
1from itertools import combinations
2
3numbers = [1, 2, 3]
4power_set = [
5    combo
6    for r in range(0, len(numbers) + 1)
7    for combo in combinations(numbers, r)
8]
9
10print(power_set)

The first item will be (), which represents the empty combination.

Use Permutations When Order Matters

If (1, 2) and (2, 1) should count as different results, you want permutations instead:

python
1from itertools import permutations
2
3numbers = [1, 2, 3]
4result = list(permutations(numbers, 2))
5print(result)

Output:

python
[(1, 2), (1, 3), (2, 1), (2, 3), (3, 1), (3, 2)]

That distinction is essential. Many bugs come from choosing combinations when the algorithm actually depends on sequence order.

Write It Yourself with Recursion

If you need to understand the mechanics, a recursive solution is educational:

python
1def combinations_of_size(values, size):
2    result = []
3
4    def backtrack(start, path):
5        if len(path) == size:
6            result.append(tuple(path))
7            return
8
9        for index in range(start, len(values)):
10            path.append(values[index])
11            backtrack(index + 1, path)
12            path.pop()
13
14    backtrack(0, [])
15    return result
16
17
18print(combinations_of_size([1, 2, 3, 4], 3))

This generates the same result as itertools.combinations, but the standard library version is faster and more memory-efficient because it is implemented in optimized native code.

Watch Out for Combinatorial Explosion

The number of results grows quickly. Even for moderate input sizes, generating every combination can become expensive in both time and memory.

For example, 20 items already produce over one million subsets if you want the full power set. That means you should prefer generators and stream the results when possible:

python
1from itertools import combinations
2
3for combo in combinations(range(100), 3):
4    process(combo)

This avoids building a massive list in memory all at once.

Common Pitfalls

  • Saying "combinations" when the real requirement is permutations.
  • Converting everything to a list too early and exhausting memory on large inputs.
  • Forgetting whether the empty set should be included.
  • Ignoring duplicate values in the input list. Position-based combinations may still produce repeated tuples if the source values repeat.
  • Reimplementing combinatorics manually when itertools already solves the problem cleanly.

Summary

  • Use itertools.combinations when order does not matter.
  • Loop over different lengths if you need every subset size.
  • Use itertools.permutations when order matters.
  • Prefer generator-based iteration for large result sets.
  • Clarify the exact meaning of "all possible combinations" before coding.

Course illustration
Course illustration

All Rights Reserved.