在MATLAB中查找多个数组的集合交集

时间:2012-12-29 08:59:01

标签: matlab rows intersection

我试图解决这个问题,但我无法实现。 你可以帮我什么吗?

问题

Mat1 | Mat2 | Mat3

 1 2 | 1 3  | 2 6

 1 3 | 2 6  | 2 5

 2 4 | 3 1  | 3 1

 3 1 | 3 5  | 5 2

 4 5 |

如果有3个矩阵(例如上面),我想以[column1 column2 matrixnumber]形式获得交叉行的结果。

以上示例的结果将是

1 3 1

1 3 2

2 6 2

2 6 3

3 1 1

3 1 2

3 1 3

如果结果的格式为[column1 column2 firstmatrix secondmatrix, ...]

,则可以
1 3 1 2

2 6 2 3

3 1 1 2 3

对于这个问题,我想最多使用一个for循环。

你对此有什么想法吗?

2 个答案:

答案 0 :(得分:4)

这里有一个替代解决方案(似乎比Gunther的运行速度快)使用MATLAB的intersect

Mat = {[1 2; 1 3; 2 4; 3 1; 4 5],
       [1 3; 2 6; 3 1; 3 5],
       [2 6; 2 5; 3 1; 5 2]};

result = zeros(sum(cellfun(@(x)size(x, 1), Mat)), 3); % # Preallocate memory
k = 1;
for cc = transpose(nchoosek(1:numel(Mat), 2))
    x = intersect(Mat{cc}, 'rows');                   % # Find intersection
    y = ones(size(x, 1), 2) * diag(cc);               % # Generate matrix indices
    result(k:k + numel(y) - 1, :) = [[x; x], y(:)];
    k = k + numel(y);
end

result(all(~result, 2), :) = [];                      % # Discard zero rows
result = unique(result, 'rows');                      % # Discard repeated rows

矩阵result现在应该包含唯一的交集行及其对应的矩阵索引,就像你想要的那样:

result =   
     1     3     1
     1     3     2
     2     6     2
     2     6     3
     3     1     1
     3     1     2
     3     1     3

答案 1 :(得分:3)

如果我理解正确,您有多组配对:Mat1Mat2Mat3,... MatN。现在,您想要找到唯一对,然后找出每个唯一对出现在哪个集合中。

如果您有大量套装,我建议您开始使用cell array来保留所有套装,让事情变得更轻松:

N = 3; % total number of data sets
Mat = cell(N,1);
Mat{1} = [1 2;
          1 3;
          2 4;
          3 1;
          4 5];
Mat{2} = [1 3;
          2 6;
          3 1;
          3 5];
Mat{3} = [2 6;
          2 5;
          3 1;
          5 2];
% etc.

首先让我们找到唯一的对:

uniq_pairs = unique(cat(1,Mat{:}),'rows');
M = size(uniq_pairs ,1);

然后使用ismember检查哪些集合包含哪些对:

matcontpair = false(M,N); %preallocate
for ii=1:N % unavoidable loop
    matcontpair(:,ii) = ismember(uniq_pairs,Mat{ii},'rows');
end

要将此交集矩阵转换为每对的一组矩阵数,请再次循环它并将最终结果存储在单元格数组中(您不能使用数组,因为它们的大小可能不同(某些对只发现一次,其他两次,其他三次......)

pair_occurence= cell(M,1);
d=1:N;
for jj=1:M
    pair_occurence{jj} = d(matcontpair(jj,:));
end

现在您有一个大小为uniq_pairs的矩阵Mx2包含唯一对,以及一个大小为pair_occurence的出现单元格数组Mx1:每个单元格对应一对包含该对存在的矩阵列表。

如果要从列表中删除仅存在于一个矩阵中的对,请使用以下命令:

% find them
lonely_pairs = cellfun(@numel,pair_occurence)<2;
% and destroy them
uniq_pairs(lonely_pairs,:) = [];
pair_occurence(lonely_pairs) = [];