user34790
user34790

Reputation: 2036

Mapping ids of two vectors

I have two vectors with the same elements but their order is not same. For eg

A

10
9 
8

B

8
9
10

I want to find the mapping between the two

B2A

3
2
1

How can I do this in matlab efficiently?

Upvotes: 1

Views: 110

Answers (4)

Luis Mendo
Luis Mendo

Reputation: 112749

I would go for Joe Serrano's answer using three chained sort's.

Another approach is to test all combinations for equality with bsxfun:

[~, B2A] = max(bsxfun(@eq, B(:), A(:).'));

This gives B2A such that B(B2A) equals A. If you want it the other way around (not clear from your example), simply reverse A and B within bsxfun.

Upvotes: 0

Joe Serrano
Joe Serrano

Reputation: 424

I think the Matlab sort is efficient. So:

[~,I]=sort(A); %sort A; we want the indices, not the values
[~,J]=sort(B); %same with B
%I(1) and J(1) both point to the smallest value, and a similar statement is true 
%for other pairs, even with repeated values.

%Now, find the index vector that sorts I
[~,K]=sort(I);

%if K(1) is k, then A(k) is the kth smallest entry in A, and the kth smallest 
%entry in B is J(k)
%so B2A(1)=J(k)=J(K(1)), where BSA is the desired permutation vector

% A similar statement holds for the other entries
%so finally

B2A=J(K); 

if the above were in script "findB2A" the following should be a check for it

N=1e4;
M=100;
A=floor(M*rand(1,N));
[~,I]=sort(rand(1,N));
B=A(I);
findB2A;
all(A==B(B2A))

Upvotes: 1

m_power
m_power

Reputation: 3204

Here a solution :

arrayfun(@(x)find(x == B), A)

I tried with bigger arrays :

A = [ 7 5 2 9 1];
B = [ 1 9 7 5 2];

It gives the following result :

ans =

 3     4     5     2     1

Edit

Because arrayfun is usually slower than the equivalent loop, here a solution with a loop:

T = length(A);
B2A = zeros(1, length(A));
for tt = 1:T
   B2A(1, tt) = find(A(tt) == B);
end

Upvotes: 0

Mad Physicist
Mad Physicist

Reputation: 114440

There are a couple of ways of doing this. The most efficient in terms of lines of code is probably using ismember(). The return values are [Lia,Locb] = ismember(A,B), where Locb are the indices in B which correspond to the elements of A. You can do [~, B2A] = ismember(A, B) to get the result you want. If your version of MATLAB does not allow ~, supply a throwaway argument for the first output.

You must ensure that there is a 1-to-1 mapping to get meaningful results, otherwise the index will always point to the first matching element.

Upvotes: 0

Related Questions