我正在编写一段代码,该代码应该在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
我的想法是对E
和T
的每一行进行排序,因此它们将按相同的顺序排列,然后将每行与循环进行比较。但是,我正在尝试学习以更多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);
更优雅的解决方案?
谢谢!
答案 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)
您可以使用bsxfun
和eq
功能执行您的要求:
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;
无需在循环中对E
和T
的每一行进行排序 - sort
将为您执行此操作。 rowsEq
是一个三维数组,表示T
的每一行中的元素与E
的每一行的相等性;如果此矩阵中连续有三个1
,则E
和T
的行相等,因此我们总结并测试1
s的数量是3(或size(T, 2)
)。我们留下一个数组,分别表示T的每一行的相等性,因此最终的sum
将这些结果组合起来给出你想要的东西。