Generate all possible combinations of the elements of some vectors (Cartesian product)

后端 未结 4 1074
南笙
南笙 2020-11-22 13:32

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条回答
  • 2020-11-22 13:47

    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);
    
    0 讨论(0)
  • 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,

    1. If you have the Neural Network Toolbox: use combvec
    2. If you do not have the toolbox, as is usually the case: below is another way to generalize the Cartesian product for any number of sets.

    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.

    0 讨论(0)
  • 2020-11-22 14:05

    we can also use the 'combvec' instruction in matlab

        no_inp=3 % number of inputs we want...in this case we have 3 inputs                  
        a=[1 2 3]
        b=[1 2 3]
        c=[1 2 3]
    
        pre_final=combvec(c,b,a)';
        final=zeros(size(pre_final));
    
        for i=1:no_inp
        final(:,i)=pre_final(:,no_inp-i+1);
        end
        final 
    

    Hope it helps. Good luck.

    0 讨论(0)
  • 2020-11-22 14:06

    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
    
    0 讨论(0)
提交回复
热议问题