user1849133
user1849133

Reputation: 527

Matching by Matlab

A =[1;2;3;4;5]
B= [10 1 ;11 2;19 5]

I want to get

D = [1 10 ;2 11; 3 -9; 4 -9; 5 19]

That is, if something in A doesn't exist in B(:,2), 2nd column of D should be -9.

If something in A exists in B(:,2), I want to put the corresponding row of 1st column of B in 2nd column of D.

I know how to do it with a mix of ismember and for and if. But I need a more elegant method which doesn't use "for" to speed it up.

Upvotes: 0

Views: 125

Answers (4)

Luis Mendo
Luis Mendo

Reputation: 112699

For general A:

A =[1;2;3;4;6]; % Note change in A
B= [10 1 ;11 2;19 5];

[aux, where] = ismember(A,B(:,2));
b_where = find(where>0);
D = [(1:length(A)).' repmat(-9,length(A),1)];
D(b_where,2) = B(where(b_where),1);

This gives

D = [ 1    10
      2    11
      3    -9
      4    -9
      5    -9 ]

Upvotes: 2

horchler
horchler

Reputation: 18484

Unless I'm missing something (or A is not a vector of indices), this is actually much simpler and doesn't require ismember or find at all, just direct indexing:

D = [A zeros(length(A),1)-9];
D(B(:,2),2) = B(:,1)

which for your example matrices gives

D =

    1    10
    2    11
    3    -9
    4    -9
    5    19

Upvotes: 4

Marc Claesen
Marc Claesen

Reputation: 17026

First create a temporary matrix:

tmp=[B; -9*ones(size(A(~ismember(A,B)))), A(~ismember(A,B))]
tmp =    
    10     1
    11     2
    19     5
    -9     3
    -9     4

Then use find to obtain the first row index with a match to elements of A in the second column of tmp (there is always a match by design).

D=[A, arrayfun(@(x) tmp(find(tmp(:,2)==x,1,'first'),1),A)];
D =    
     1    10
     2    11
     3    -9
     4    -9
     5    19

As an alternative for the second step, you could simply sort tmp based on its second column:

[~,I]=sort(tmp(:,2));
D=[tmp(I,2), tmp(I,1)]
D =
    1    10
    2    11
    3    -9
    4    -9
    5    19

Upvotes: 0

Engineero
Engineero

Reputation: 12928

I am not sure how efficient this solution is, but it avoids using any loops so at least it would be a place to start:

D = [A -9*ones(size(A))];           % initialize your result
[tf, idx] = ismember(A, B(:,2));    % get indices of matching elements
idx(idx==0) = [];                   % trim the zeros
D(find(tf),2) = B(idx,1);           % set the matching entries in D to the appropriate entries in B

disp(E)

You allocate your matrix ahead of time to save time later on (building up matrices dynamically is really slow in MATLAB). The ismember call is returning the true-false vector tf showing which elements of A correspond to something in B, as well as the associated index of what they correspond to in idx. The problem with idx is that it contains a zero any time ft is zero, which is why we have the line idx(idx==0) = []; to clear out these zeros. Finally, find(tf) is used to get the indices associated with a match on the destination (rows of D in this case), and we set the values at those indices equal to the corresponding value in B that we want.

Upvotes: 1

Related Questions