2

Suppose I have a matrix A, containing possible value pairs and a matrix B, containing all value pairs:

    A = [1,1;2,2;3,3];
    B = [1,1;3,4;2,2;1,1];

I would like to create a matrix C that contains all pairs that are allowed by A (i.e. C = [1,1;2,2;1,1]).

Using C = ismember(A,B,'rows') will only show the first occurence of 1,1, but I need both.

Currently I use a for-loop to create C, which looks like:

    TFtot = false(size(B(:,1,1),1);
    for i = 1:size(a(:,1),1)
        TF1 = A(i,1) == B(:,1) & A(i,2) = B(:,2);
        TFtot = TF1 | TFtot;
    end

    C = B(TFtot,:);

I would like to create a faster approach, because this loop currently greatly slows down the algorithm.

Divakar
  • 218,885
  • 19
  • 262
  • 358
Paul W
  • 83
  • 2
  • `TFTot` will either be `0` or `1` depending on whether or not you have found **any** match in `B` using any row from `A`. Your code will only select out the first row of `B` if at all. You should probably make `TFtot` an array that keeps track of whether we have found the particular row in `B` in `A`. Also, `A(i,2) = B(:,2)` should really be `A(i,2) == B(:,2)`.... but comparing a scalar to a vector will yield true *unless all* values in the comparison result are 0. You should use `any/all` in that case. – rayryeng Jul 30 '15 at 15:10

3 Answers3

2

You're pretty close. You just need to swap B and A, then use this output to index into B:

L = ismember(B, A, 'rows');
C = B(L,:);

How ismember works in this particular case is that it outputs a logical vector that has the same number of rows as B where the ith value in B tells you whether we have found this ith row somewhere in A (logical 1) or if we haven't found this row (logical 0).

You want to select out those entries in B that are seen in A, and so you simply use the output of ismember to slice into B to extract out the affected rows, and grab all of the columns.

We get for C:

>> C

C =

     1     1
     2     2
     1     1
rayryeng
  • 102,964
  • 22
  • 184
  • 193
2

Here's an alternative using bsxfun:

C = B(all(any(bsxfun(@eq, B, permute(A, [3 2 1])),3),2),:);

Or you could use pdist2 (Statistics Toolbox):

B(any(~pdist2(A,B),1),:);
Luis Mendo
  • 110,752
  • 13
  • 76
  • 147
2

Using matrix-multiplication based euclidean distance calculations -

Bt = B.';  %//'
[m,n] = size(A);
dists = [A.^2 ones(size(A)) -2*A ]*[ones(size(Bt)) ; Bt.^2 ; Bt];
C = B(any(dists==0,1),:);
Community
  • 1
  • 1
Divakar
  • 218,885
  • 19
  • 262
  • 358