I would like to generate all the possible combinations of the elements of a given number of vectors.
For example, for [1 2]
, [1 2]
and [4 5]
I want to generate the elements:
[1 1 4; 1 1 5; 1 2 4; 1 2 5; 2 1 4; 2 1 5; 2 2 4; 2 2 5]
The problem is that I don't know the number of vectors for which I need to calculate the combinations. There might be 3 as in this case, or there may be 10, and I need a generalization. Can you please help me to this in MATLAB? Is there already a predefined function that can do this task?
Consider this solution using the NDGRID function:
sets = {[1 2], [1 2], [4 5]};
[x y z] = ndgrid(sets{:});
cartProd = [x(:) y(:) z(:)];
cartProd =
1 1 4
2 1 4
1 2 4
2 2 4
1 1 5
2 1 5
1 2 5
2 2 5
Or if you want a general solution for any number of sets (without having to create the variables manually), use this function definition:
function result = cartesianProduct(sets)
c = cell(1, numel(sets));
[c{:}] = ndgrid( sets{:} );
result = cell2mat( cellfun(@(v)v(:), c, 'UniformOutput',false) );
end
Note that if you prefer, you can sort the results:
cartProd = sortrows(cartProd, 1:numel(sets));
Also, the code above does not check if the sets have no duplicate values (ex: {[1 1] [1 2] [4 5]}
). Add this one line if you want to:
sets = cellfun(@unique, sets, 'UniformOutput',false);
Try ALLCOMB function at FileExchange.
If you store you vectors in a cell array, you can run it like this:
a = {[1 2], [1 2], [4 5]};
allcomb(a{:})
ans =
1 1 4
1 1 5
1 2 4
1 2 5
2 1 4
2 1 5
2 2 4
2 2 5
This late answers provides two additional solutions, where the second is the solution (in my opinion) and an improvement on Amro's answer solution with ndgrid
by applying MATLAB's powerful comma-separated lists instead of cell arrays for high performance,
combvec
Just as Amro did in his answer, the comma-separated lists syntax (v{:}
) supplies both the inputs and outputs of ndgrid
. The difference (fourth line) is that it avoids cellfun
and cell2mat
by applying comma-separated lists, again, now as the inputs to cat
:
N = numel(a);
v = cell(N,1);
[v{:}] = ndgrid(a{:});
res = reshape(cat(N+1,v{:}),[],N);
The use of cat
and reshape
cuts execution time almost in half. This approach was demonstrated in my answer to an different question, and more formally by Luis Mendo.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With