Finding correct row in array with multiple columns matching different conditions

61 views (last 30 days)
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

Accepted Answer

DGM
DGM on 25 Apr 2021
Edited: DGM on 25 Apr 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 Comments
Avinash Rajendra
Avinash Rajendra on 25 Apr 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 on 25 Apr 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.

Sign in to comment.

More Answers (1)

the cyclist
the cyclist on 25 Apr 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

Categories

Find more on Loops and Conditional Statements in Help Center and File Exchange

Products

Community Treasure Hunt

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

Start Hunting!