查找二维矩阵的逐行组合

Posted

技术标签:

【中文标题】查找二维矩阵的逐行组合【英文标题】:Find row-wise combinations of a 2 dimensional matrix 【发布时间】:2014-12-02 19:18:45 【问题描述】:

我有一个矩阵:

X = [2,6,1; 3,8,1; 4,7,1; 6,2,1; 6,4,1; 7,3,1; 8,5,1; 7,6,1];

我想找到 X 的所有按行组合。即

A(1) = [2, 6, 1; 3, 8, 1; 4, 7, 1]
A(2) = [2, 6, 1; 3, 8, 1; 6, 2, 1]
:
:
:

这是我尝试过的:

X = [2,6,1; 3,8,1; 4,7,1; 6,2,1; 6,4,1; 7,3,1; 8,5,1; 7,6,1];
p = 3
[m, n] = size(X);
comb = combnk(1:m, p);
[s, t] = size(comb);
c = [X(comb(:,1), :, :) X(comb(:,2), :, :) X(comb(:,3), :, :)];

这给了我一个像这样的矩阵:

c = 2     6     1     3     8     1     4     7     1
    2     6     1     3     8     1     6     2     1
    2     6     1     3     8     1     6     4     1

我想应用连接矩阵选项来获得 c 以使其根据 p 的值动态,但我不确定如何使用它。我不想使用 For 循环。请帮帮我。

【问题讨论】:

你不是说上面的c = [X(comb(1,:), :, :)...吗? 你的标题也是 3D 矩阵,但你的例子是 2D...? 【参考方案1】:

这是完全矢量化的,所以应该很快:

n = 3; %// number of rows to pick each time
ind = reshape(nchoosek(1:size(X,1), n).', [], 1); %'// indices of combinations
A = permute(reshape(X(ind,:).', size(X,2), n, []), [2 1 3]);

结果是

A(:,:,1)
ans =
     2     6     1
     3     8     1
     4     7     1

A(:,:,2)
ans =
     2     6     1
     3     8     1
     6     2     1

等等

如果您需要单元格数组形式的结果,您可以通过这种方式将A 从 3D 数组转换为单元格数组:

A = mat2cell(A, size(A,1), size(A,2), ones(1,size(A,3)));

【讨论】:

谢谢路易斯。完美运行!【参考方案2】:

你的想法很接近。这段代码完成了这项工作。我把cmets放在代码里,应该很容易阅读。

X = [2,6,1; 3,8,1; 4,7,1; 6,2,1; 6,4,1; 7,3,1; 8,5,1; 7,6,1];
p = 3;
%// List all combinations choosing 3 out of 1:8.
v = nchoosek(1:size(X,1), p);
%// Use each row of v to create the matrices, and put the results in an cell array.
%// This is the A matrix in your question.
A = arrayfun(@(k)X(v(k,:), :), 1:size(v,1), 'UniformOutput', false);
%// And you can concatenate A vertically to get c.
flatA = cellfun(@(x)reshape(x, 1, []), A, 'UniformOutput', false);
c = vertcat(flatA:);

PS:据我了解,我认为您想要的结果是 A,这是一个易于使用的元胞数组。但是为了以防万一,我添加了一个额外的步骤来获得 c 与您的问题完全相同。

免责声明:arrayfun 和 cellfun 在性能方面几乎等同于 for 循环。

【讨论】:

同意 - 此代码不会“在没有循环的情况下完成工作”,因为 arrayfun 和现在的 cellfun 都只是具有额外开销的循环。 -1,直到您删除“无循环”的行 已按照建议删除。我并没有试图欺骗。很多时候人们要求“无循环”只是因为单线看起来不错:) @xmo -1 已删除,但在这种情况下,您应该添加一个免责声明,即引擎盖下有循环,而不是说没有循环。如果是我的,我仍然会在您的回答中添加这样的免责声明 我不知道这个事实。 添加了免责声明。如果性能是一个问题,Luis 的回答应该更快。【参考方案3】:

您可以使用reshape 和一堆转置来完成,因为 Matlab 是列-major ordered:

c = reshape(X(comb',:)',9,[])'

或者如果你想要一个 3D 矩阵:

A = permute(reshape(X(comb',:)',3,3,[])', [2,1,3])

【讨论】:

感谢 Dan 指出我的错误。我已经改变了。代码工作正常,但我想要的是: A(1) = [2, 6, 1; 3、8、1; 4, 7, 1] 而这会返回 [2 6 1 3 8 1 4 7 1] 这可能是一个愚蠢的问题,但我尝试了很多仍然无法做到。 两者都很好,但 A(1) 更可取。 @Learner23 我非常不同意,我想你会发现在尺寸允许的情况下,3D 数值矩阵比元胞数组更容易使用(在你的情况下他们这样做)跨度>

以上是关于查找二维矩阵的逐行组合的主要内容,如果未能解决你的问题,请参考以下文章

二维数组3:搜索二维矩阵

二维数组(矩阵)元素查找

二分查找74. 搜索二维矩阵

leetcode(74)----搜索二维矩阵(二分查找)

二维数组中的查找(杨氏矩阵(C语言+Java))

LeetCode74. 搜索二维矩阵