我想生成给定数量的向量元素的所有可能组合。
例如,对于[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中帮助我完成这个任务?是否已经有预定义的函数可以执行此任务?
我想生成给定数量的向量元素的所有可能组合。
例如,对于[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中帮助我完成这个任务?是否已经有预定义的函数可以执行此任务?
考虑使用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);
请在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
这篇晚回答提供了两个额外的解决方案,其中第二个是我认为更好的解决方案,并且使用MATLAB强大的逗号分隔列表而不是单元数组以获得高性能的Amro答案解决方案的改进。
combvec
与Amro在他的答案中所做的一样,逗号分隔的列表语法(v{:}
)提供了ndgrid
函数的输入和输出。区别(第四行)在于它通过再次应用逗号分隔的列表作为cat
函数的输入来避免cellfun
和cell2mat
函数:
N = numel(a);
v = cell(N,1);
[v{:}] = ndgrid(a{:});
res = reshape(cat(N+1,v{:}),[],N);
使用 cat
和 reshape
几乎可以将执行时间缩短一半。在 我的另一个回答 中演示了这种方法,并且 由Luis Mendo更正式地进行了展示。
n
的向量的长度为m
的所有排列:[v {1:m}] = ndgrid(1:n);
和res = reshape(cat(m + 1,v {:}),[],m)
。 - obchardoncombinations
函数,该函数支持向量、矩阵、单元数组以及它们的混合使用。>> 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
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
combinations
行为的适配器,并且支持混合类型。function grid = combinations(varargin)
grid = cell(nargin, 1);
[grid{:}] = ndgrid(varargin{:});
combos = cellfun(@(it) it(:), grid, 'UniformOutput', false)';
combos = table(combos{:});
end
我们还可以在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