生成某些向量元素的所有可能组合(笛卡尔积)

发布于 2024-10-02 07:12:32 字数 300 浏览 9 评论 0原文

我想生成给定数量的向量的元素的所有可能的组合。

例如,对于 [1 2][1 2][4 5] 我想生成元素:

[ 1 1 4; 1 1 5; 1 2 4; 1 2 5; 2 1 4; 2 1 5; 2 2 4; 2 2 5]

问题是我不知道需要计算组合的向量数量。在本例中可能有 3 个,也可能有 10 个,我需要一个概括。你能在 MATLAB 中帮我解决这个问题吗?是否已经有一个预定义函数可以完成此任务?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

千仐 2024-10-09 07:12:32

考虑使用 NDGRID 函数解决此解决方案:

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

或者如果您想要通用解决方案对于任意数量的集合(无需手动创建变量),请使用此函数定义:

function result = cartesianProduct(sets)
    c = cell(1, numel(sets));
    [c{:}] = ndgrid( sets{:} );
    result = cell2mat( cellfun(@(v)v(:), c, 'UniformOutput',false) );
end

请注意,如果您愿意,可以对结果进行排序:

cartProd = sortrows(cartProd, 1:numel(sets));

此外,上面的代码不会检查集合是否没有重复值(例如: {[1 1] [1 2] [4 5]})。如果您想添加这一行:

sets = cellfun(@unique, sets, 'UniformOutput',false);

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);
愿得七秒忆 2024-10-09 07:12:32

尝试 FileExchange 中的 ALLCOMB 函数。

如果将向量存储在元胞数组中,则可以像这样运行它:

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

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
风为裳 2024-10-09 07:12:32

这个最新的答案提供了两个额外的解决方案,其中第二个是解决方案(在我看来)以及通过应用 MATLAB 强大的逗号分隔列表对 Amro 的答案解决方案与 ndgrid 的改进而不是高性能的元胞数组,

  1. 如果您有神经网络工具箱:使用 < code>combvec
  2. 如果您没有工具箱(通常是这种情况):下面是推广任意数量集合的笛卡尔积的另一种方法。

正如 Amro 在他的回答中所做的那样,逗号分隔的列表语法 (v{:}) 提供了 ndgrid 的输入和输出。不同之处(第四行)是,它通过应用逗号分隔列表来避免 cellfuncell2mat,现在再次作为 cat 的输入:

N = numel(a);
v = cell(N,1);
[v{:}] = ndgrid(a{:});
res = reshape(cat(N+1,v{:}),[],N);

使用 catreshape 将执行时间几乎减少一半。 我对另一个问题的回答更正式的是路易斯·门多

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.

红衣飘飘貌似仙 2024-10-09 07:12:32

从 MATLAB 2023a 开始,您可以使用 combinations 函数,支持向量、矩阵、元胞数组及其混合:

>> combinations([1 2], [1 2], [4 5])

ans =

  8×3 table

    Var1    Var2    Var3
    ____    ____    ____

     1       1       4  
     1       1       5  
     1       2       4  
     1       2       5  
     2       1       4  
     2       1       5  
     2       2       4  
     2       2       5  

输出的形式为 table,支持混合类型。如果您的输出仅需要单一类型,您可以使用 table2array

>> table2array(combinations([1 2], [1 2], [4 5]))

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

就其价值而言,我编写了一个填充程序来模拟旧版本 MATLAB(低至版本 2013b)中组合的行为,包括对混合的支持类型:

function grid = combinations(varargin)
    grid = cell(nargin, 1);
    [grid{:}] = ndgrid(varargin{:});

    combos = cellfun(@(it) it(:), grid, 'UniformOutput', false)';
    combos = table(combos{:});
end

Since MATLAB 2023a you can use the combinations function, which supports vectors, matrices, cell arrays, and mixtures thereof:

>> combinations([1 2], [1 2], [4 5])

ans =

  8×3 table

    Var1    Var2    Var3
    ____    ____    ____

     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 output is in the form of a table, which supports mixed types. If your outputs need only a single type, you can convert the output to a matrix using table2array:

>> table2array(combinations([1 2], [1 2], [4 5]))

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

For what it's worth, I have written a shim that emulates the behaviour of combinations in older versions of MATLAB (down to version 2013b), including support for mixed types:

function grid = combinations(varargin)
    grid = cell(nargin, 1);
    [grid{:}] = ndgrid(varargin{:});

    combos = cellfun(@(it) it(:), grid, 'UniformOutput', false)';
    combos = table(combos{:});
end
醉态萌生 2024-10-09 07:12:32

我们还可以在 matlab 中使用“combvec”指令

    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 

希望它有帮助。
祝你好运。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文