查找矩阵中行的排列

时间:2013-05-26 09:50:16

标签: matlab matrix

我正在编写一段代码,该代码应该在Nx3矩阵E中找到包含Mx3矩阵T的值的行,但它们不一定是相同的顺序。我写了一些有用的东西,但是我对这个样式并不满意,并希望使用ismember和find来对矩阵应用逻辑运算,而不是我正在使用的循环:

E = [7 36 37; 9 1 5; 4 34 100; 4 12 33; 4 34 33];
T = [37 7 36; 4 34 33];      

for i=1:size(T,1)
    T(i,:) = sort(T(i,:));
end

for i=1:size(E,1)
    E(i,:) = sort(E(i,:));
end

res = zeros(size(T,1),1);
for i=1:size(T,1)
    a = ismember(E,t(i,:));    
    res(i,1) = find(sum(a,2)==3);
end

我的想法是对ET的每一行进行排序,因此它们将按相同的顺序排列,然后将每行与循环进行比较。但是,我正在尝试学习以更多MATLAB风格编写代码并希望应用ismember并且可能会发现执行相同的操作。像这样:

a = sum(ismember(E,T(1,1))~=0,2);
b = sum(ismember(E,T(1,2))~=0,2);
c = sum(ismember(E,T(1,3))~=0,2);
r = find(a&b&c);

更优雅的解决方案?

谢谢!

2 个答案:

答案 0 :(得分:3)

您可以将ismember'rows'选项一起使用:

ismember(sort(E, 2), sort(T, 2), 'rows')

这将生成一个逻辑(布尔)向量,指示矩阵T(或其任何排列)的哪些行出现在矩阵E中。请注意,每行都是独立排序的,以处理重新排序。

如果您需要T行的索引,请使用ismember的两个输出:

[tf, loc] = ismember(sort(E, 2), sort(T, 2), 'rows')

注意:如果您的数据包含浮点数,ismember方法可能会失败,因此您需要设置容差以进行比较。请参阅this answer以获得更强大的替代方法(并记住首先沿2 nd 维度对输入矩阵进行排序!)。

实施例

E = [7 36 37; 9 1 5; 4 34 100; 4 12 33; 4 34 33];
T = [37 7 36; 4 34 33];
[tf, loc] = ismember(sort(E, 2), sort(T, 2), 'rows');

结果是:

tf =          loc =
     1              1
     0              0
     0              0
     0              0
     1              2

答案 1 :(得分:1)

您可以使用bsxfuneq功能执行您的要求:

Esorted = sort(E, 2);
Tsorted = sort(T, 2);

rowsEq = bsxfun(@eq, Esorted, permute(Tsorted, [3 2 1]));
rowsEqInd = sum(rowsEq, 2) == size(T, 2);
EEqInd = sum(rowsEqInd, 3) > 0;

无需在循环中对ET的每一行进行排序 - sort将为您执行此操作。 rowsEq是一个三维数组,表示T的每一行中的元素与E的每一行的相等性;如果此矩阵中连续有三个1,则ET的行相等,因此我们总结并测试1 s的数量是3(或size(T, 2))。我们留下一个数组,分别表示T的每一行的相等性,因此最终的sum将这些结果组合起来给出你想要的东西。