枚举单元格的组合

时间:2018-07-25 19:20:50

标签: matlab combinations cell-array

说我有3个牢房:

M1={ [1,1,1], [2,2,2] }
M2={ [3,3], [4,4] }
M3={ [5], [6] }

我想获取M1中的每个元素,将其与M2的每个元素组合,并将其与M3的每个元素,等等。

对于上面的输入,我想产生一个像这样的巨型细胞:

[1,1,1],[3,3],[5]
[1,1,1],[3,3],[6]
[1,1,1],[4,4],[5]
[1,1,1],[4,4],[6]
[2,2,2],[3,3],[5]
[2,2,2],[3,3],[6]
[2,2,2],[4,4],[5]
[2,2,2],[4,4],[6]

我该怎么做?通常,单元格(M1,M2...Mn)的数量及其大小是未知的(并且正在变化)。

2 个答案:

答案 0 :(得分:1)

此功能可以满足您的要求:

function C = add_permutations(A,B)
% A is a cell array NxK, B is 1xM
% C is a cell array N*M x K+1
N = size(A,1);
A = reshape(A,N,1,[]);
C = cat(3,repmat(A,1,numel(B)),repmat(B,N,1));
C = reshape(C,[],size(C,3));

它创建两个单元格数组的所有组合,方法是将它们复制到不同的维度,然后沿第3维连接并折叠前两个维。因为我们想用不同的单元格数组重复调用它,所以输入AN x K)每行都有K个矩阵,这些是先前的组合。 B是一个单元向量,每个元素将与A的每一行结合。

您可以按以下方式使用它:

M1 = { 'a', 'b', 'c', 'd' }; % These are easier for debugging than OP's input, but cell elements can be anything at all.
M2 = { 1, 2 };
M3 = { 10, 12 };

X = M1.';
X = add_permutations(X,M2);
X = add_permutations(X,M3);

X现在包含:

X =

  16×3 cell array

    'a'    [1]    [10]
    'b'    [1]    [10]
    'c'    [1]    [10]
    'd'    [1]    [10]
    'a'    [2]    [10]
    'b'    [2]    [10]
    'c'    [2]    [10]
    'd'    [2]    [10]
    'a'    [1]    [12]
    'b'    [1]    [12]
    'c'    [1]    [12]
    'd'    [1]    [12]
    'a'    [2]    [12]
    'b'    [2]    [12]
    'c'    [2]    [12]
    'd'    [2]    [12]

答案 1 :(得分:0)

这不是一个排列,而是一个枚举:您有3个符号,每个符号都有2个可能的值,而您只是在枚举所有可能的“数字”。您可以像计算3位数的二进制数一样来思考它。

在这种情况下,枚举所有这些可能性的一种方法是使用ndgrid。如果M1具有n1个元素,则M2具有n2个元素,依此类推:

n1 = numel(M1);
n2 = numel(M2);
n3 = numel(M3);

[a,b,c] = ndgrid(1:n1, 1:n2, 1:n3);

此处a,b,c是每个3维数组,它们表示组合的“网格”。显然,您不需要这样做,因此可以对它们进行矢量化处理,并使用它们来创建M1, M2, M3中各种元素的组合,就像这样

vertcat( M1(a(:)), M2(b(:)), M3(c(:)) )

如果您有兴趣对任意数量的M进行概括,也可以这样做,但是请记住,随着尺寸的增加,这些“网格”的增长非常快。

注意: vertcat代表“垂直串联”,之所以垂直而不是水平,是因为M1(a(:))的结果是一个行形单元,甚至尽管a(:)是列向量。那只是索引头痛,但如果需要Nx3,您可以简单地转置结果。