Search code examples
arraysmatlabmatrixcombinationscartesian-product

Generate a matrix containing all combinations of elements from n vectors (Cartesian product)


This question pops up quite often in one form or another (see for example here or here). So I thought I'd present it in a general form, and provide an answer which might serve for future reference.

Given an arbitrary number n of vectors of possibly different sizes, generate an n-column matrix whose rows describe all combinations of elements taken from those vectors (Cartesian product) .

For example,

vectors = { [1 2], [3 6 9], [10 20] }

should give

combs = [ 1     3    10
          1     3    20
          1     6    10
          1     6    20
          1     9    10
          1     9    20
          2     3    10
          2     3    20
          2     6    10
          2     6    20
          2     9    10
          2     9    20 ]

Solution

  • The ndgrid function almost gives the answer, but has one caveat: n output variables must be explicitly defined to call it. Since n is arbitrary, the best way is to use a comma-separated list (generated from a cell array with ncells) to serve as output. The resulting n matrices are then concatenated into the desired n-column matrix:

    vectors = { [1 2], [3 6 9], [10 20] }; %// input data: cell array of vectors
    
    n = numel(vectors); %// number of vectors
    combs = cell(1,n); %// pre-define to generate comma-separated list
    [combs{end:-1:1}] = ndgrid(vectors{end:-1:1}); %// the reverse order in these two
    %// comma-separated lists is needed to produce the rows of the result matrix in
    %// lexicographical order 
    combs = cat(n+1, combs{:}); %// concat the n n-dim arrays along dimension n+1
    combs = reshape(combs,[],n); %// reshape to obtain desired matrix