Finding correct row in array with multiple columns matching different conditions

22 vues (au cours des 30 derniers jours)
I have the following example and want to find the correct row. I have a for loop that does the job, but need an alternative solution for performance and efficiency reasons. Any help will be appreciated. Thanks in advance!
A = [1 2 3;
4 5 6]; % 2 rows and 3 columns
B = [1 1 2;
1 2 3;
2 2 4;
3 4 5;
4 5 6]; % 5 rows and 3 columns
What I need is the row in B where all the values of the row are respectively equal to the values of one subject row in A. In the example, all the values of the second row of B match all the values of the first row of A, and similarly with the fifth row of B and the second row of A. So, my output should be [2; 5]. One point to note is that there will only be one row in B where all its values will match those of the subject row in A.
My for loop works like this:
indices = ones(size(A, 1), 1); %size of indices = 2 rows and 1 column
for k = 1:size(A, 1) %k will go from 1 to 2; k defines subject row
C = A(k, 1:end); % C = [1 2 3] for k = 1, C = [4 5 6] for k = 2
D = find(B(1:end, 1) == C(1); % 1 and 2 for k = 1, 5 for k = 2
E = find(B(1:end, 2) == C(2); % 2 and 3, 5 for k = 2
F = find(B(1:end, 3) == C(3); % 2 for k = 1, 5 for k = 2
indices(k, 1) = intersect(intersect(D, E), F); % 2 for k = 1, 5 for k = 2
end

Réponse acceptée

DGM
DGM le 25 Avr 2021
Modifié(e) : DGM le 25 Avr 2021
Maybe something like this:
A = [1 2 3; 4 5 6]; % 2 rows and 3 columns
B = [1 1 2; 1 2 3; 2 2 4; 3 4 5; 4 5 6]; % 5 rows and 3 columns
% this is a logical index of the rows which match
C = any(all(bsxfun(@eq,B,permute(A,[3 2 1])),2),3)
gives
C =
5×1 logical array
0
1
0
0
1
For most indexing purposes, this may suffice. If you really need the list of row subscripts, just do
C = find(C)
  2 commentaires
Avinash Rajendra
Avinash Rajendra le 25 Avr 2021
The answer quotes the ismember function, which I found works perfectly for this problem. But, your answer works as well, so I'm accepting it. Thanks!
DGM
DGM le 25 Avr 2021
For what it's worth, I consider ismember() a matter of convenience. It gives the correct answers and the syntax is simple, but if speed is of value, there are usually better options. On my system, in either R2015b or R2019b, this:
C = ismember(B,A,'rows');
takes about 13-14 times as long as this convoluted mess:
C = any(all(bsxfun(@eq,B,permute(A,[3 2 1])),2),3);
Your case likely doesn't need the speed, but it's good to be aware of the penalties so that you can make the judgement when it does matter.

Connectez-vous pour commenter.

Plus de réponses (1)

the cyclist
the cyclist le 25 Avr 2021
A = [1 2 3;
4 5 6]; % 2 rows and 3 columns
B = [1 1 2;
1 2 3;
2 2 4;
3 4 5;
4 5 6]; % 5 rows and 3 columns
indices = find(ismember(B,A,'rows'))
indices = 2×1
2 5

Catégories

En savoir plus sur Matrix Indexing dans Help Center et File Exchange

Produits

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by