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:
You can generate all pairs like this:
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.
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:
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:
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:
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_000gives one million pairs' - '
10_000 x 10_000gives 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
repeatandtileis another solid NumPy option. - Be mindful of output size because combinations grow multiplicatively.

