NumPy
arrays
combinations
Python
programming

Using NumPy to build an array of all combinations of two arrays

Master System Design with Codemia

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

Introduction

If you want every pair formed by one value from array a and one value from array b, you are building a Cartesian product. In NumPy, the cleanest dense solution is usually np.meshgrid followed by reshaping, because it keeps the operation vectorized and easy to extend.

A Straightforward NumPy Solution

Suppose you start with two one-dimensional arrays:

python
1import numpy as np
2
3a = np.array([1, 2, 3])
4b = np.array([10, 20])

You can generate all pairs like this:

python
1grid_a, grid_b = np.meshgrid(a, b, indexing="ij")
2pairs = np.stack((grid_a, grid_b), axis=-1).reshape(-1, 2)
3
4print(pairs)
text
1[[ 1 10]
2 [ 1 20]
3 [ 2 10]
4 [ 2 20]
5 [ 3 10]
6 [ 3 20]]

This works because meshgrid expands each input into aligned coordinate grids. Stacking and reshaping then turns those coordinate positions into rows of pairs.

Why indexing="ij" Helps

np.meshgrid defaults to Cartesian indexing, which is often fine for plotting but can feel backward when you are thinking in row-major array terms. Using indexing="ij" makes the first input vary slowest and the second vary fastest, which usually matches how people expect combinations to be ordered.

python
1grid_a, grid_b = np.meshgrid(a, b, indexing="ij")
2
3print(grid_a)
4print(grid_b)
text
1[[1 1]
2 [2 2]
3 [3 3]]
4[[10 20]
5 [10 20]
6 [10 20]]

That layout makes it easier to see why the reshaped result becomes the full set of pairs.

A Broadcasting Alternative

For two arrays, you can also use broadcasting directly:

python
1import numpy as np
2
3a = np.array([1, 2, 3])
4b = np.array([10, 20])
5
6pairs = np.column_stack((
7    np.repeat(a, len(b)),
8    np.tile(b, len(a)),
9))
10
11print(pairs)

This produces the same result. It is efficient and explicit, but meshgrid often generalizes more naturally when you move beyond two dimensions or when the intermediate grids are useful on their own.

Extending the Idea Beyond Two Arrays

If you later need combinations of three arrays, the same pattern still works:

python
1import numpy as np
2
3a = np.array([1, 2])
4b = np.array([10, 20])
5c = np.array([100, 200])
6
7grids = np.meshgrid(a, b, c, indexing="ij")
8triples = np.stack(grids, axis=-1).reshape(-1, 3)
9
10print(triples)

That is one reason NumPy users often prefer the meshgrid approach. The shape logic stays consistent as dimensionality grows.

When NumPy Is the Right Tool

NumPy is a good fit when:

  • the inputs are already arrays
  • you want a vectorized result
  • the combinations feed later numeric processing
  • you care about staying in array form instead of Python tuples

If you only need a few small combinations for general Python logic, itertools.product may be simpler:

python
1from itertools import product
2
3pairs = list(product([1, 2, 3], [10, 20]))
4print(pairs)

That returns Python tuples rather than a NumPy array, which may or may not be what the rest of your pipeline needs.

Watch the Size of the Result

The number of rows grows multiplicatively. If a has m elements and b has n, the output has m * n rows. That can become large very quickly:

  • '1_000 x 1_000 gives one million pairs'
  • '10_000 x 10_000 gives one hundred million pairs'

At that point, memory use matters more than elegance. If the product is huge, consider whether you really need the dense materialized result or whether a streaming approach would be better.

Common Pitfalls

The biggest pitfall is forgetting that meshgrid creates coordinate grids first, not the final paired rows. You still need stack plus reshape to get the common n x 2 output format.

Another mistake is using the default indexing mode and then being surprised by row order. If order matters, set indexing="ij" explicitly.

It is also easy to allocate enormous arrays accidentally. The Cartesian product grows fast, so check sizes before materializing the result.

Finally, choose the representation that matches the next step. If downstream code expects tuples or an iterator, itertools.product may be clearer than forcing everything through NumPy.

Summary

  • The Cartesian product of two arrays is easy to build with np.meshgrid.
  • Use np.stack(...).reshape(-1, 2) to turn coordinate grids into pair rows.
  • 'indexing="ij" usually gives the most intuitive ordering.'
  • Broadcasting with repeat and tile is another solid NumPy option.
  • Be mindful of output size because combinations grow multiplicatively.

Course illustration
Course illustration

All Rights Reserved.