Finding the indices of the elements of one array in another

624 visualizaciones (últimos 30 días)
Alan
Alan el 3 de Dic. de 2011
Comentada: David el 18 de En. de 2020
Given two vectors A and B, find the index, idx into A of the element of B so that
A(idx)=B.
Now I know there must be many ways it can be done, but is there a one-liner?
For example if
A=[3 4 5 6 7];
B=[6 4 7];
then
[tf,loc]=ismember(A,B);
idx=[1:length(A)];
idx=idx(tf);
idx=idx(loc(tf));
disp(A(idx))
will do it but that is four steps. Is there a more elegant way?
  3 comentarios
Philip
Philip el 26 de Sept. de 2014
MATLAB supports logical indexing. No need to use "find":
A = A( ismember( A, B ) );
Leandro Coelho
Leandro Coelho el 1 de Jul. de 2016
Another option: intersect(A,B)

Iniciar sesión para comentar.

Respuesta aceptada

Sven
Sven el 3 de Dic. de 2011
Editada: MathWorks Support Team el 9 de Nov. de 2018
There are a few options to get the indices you are looking for. The following output indices (idx) preserve the order in A of the shared values:
[sharedvals,idx] = intersect(A,B,stable)
You can also use the following command if the order in A is not necessary:
[tf,idx] = ismember(B,A)
  3 comentarios
Alan
Alan el 3 de Dic. de 2011
I am wondering though if "intersect" and "sort" would be expensive on large arrays.
tc88
tc88 el 22 de Ag. de 2016
meanwhile, the functionality of intersect has changed and a one-line solution is also possible using intersect:
[sharedVals,idxsIntoA] = intersect(B,A,'stable')
Be aware that the order of A and B must be changed, since the order of the first argument is retained.

Iniciar sesión para comentar.

Más respuestas (6)

Alan
Alan el 3 de Dic. de 2011
Thanks for the three solutions. Here is a function to test all three. "method_1" wins as the most elegant and fastest, but the other two taught other useful ways of looking at the problem.
function test_solution
% set up the problem
N=1e6;
% A is a random vector of the integers to N
A=randperm(N);
% B is another vector of integers
B=[ 2 1 4 3 ];
% I'd like to find the indicies of the element of B in A
% such that A(idx)=B;
tic
idx=method_1(A,B);
toc
disp(A(idx));
tic
idx=method_2(A,B);
toc
disp(A(idx));
tic
idx=method_3(A,B);
toc
disp(A(idx));
function idx = method_1(A,B)
idx = arrayfun(@(x)find(A==x,1),B);
function idx = method_2(A,B)
[~,idx1] = intersect(A,B);
[~,idx2] = sort(B);
idx=idx1(idx2);
function idx = method_3(A,B)
[A,idx1] = sort(A);
[~,idx2] = histc(B,A);
idx = idx1(idx2);
  3 comentarios
Iftikhar Ali
Iftikhar Ali el 18 de Oct. de 2015
Method 3 has solved my problem, thanks.
David
David el 18 de En. de 2020
Method one also works if there are multiple occurences of B in A. Intersect fails in this case.

Iniciar sesión para comentar.


Alan
Alan el 6 de Dic. de 2011
Thinking again, I realize that ismember is all I need
[~,idx]=ismember(B,A)
will do it.
  2 comentarios
normanius
normanius el 9 de Oct. de 2017
This is by far the best answer!
John Sogade
John Sogade el 2 de En. de 2020
obviously this will fail to get A(idx), if any elements of idx are 0 (i.e. B not in A) and robust usage should be clarified to A(idx(idx ~= 0)).

Iniciar sesión para comentar.


Iftikhar Ali
Iftikhar Ali el 18 de Oct. de 2015
I am facing an issue finding indices of element matching in two arrays.
xpts = [0 0.0004 0.0011 0.0018 0.0025 0.003]; x = 0:0.0001:0.003; index1 = find(ismember(x, xpts));
It returns index1 = [1 5 12 26 31]
but there is one more element '0.0018' in x which also belongs xpts, and not including in the answer.
Similarly when I increase the number of points in x, there are few elements that are missed or not recognized by the find command. What's going wrong here.

Teja Muppirala
Teja Muppirala el 3 de Dic. de 2011
If A is sorted, then I think this is probably the easiest (and also fastest?) way to do it.
[~,idx] = histc(B,A)
If A is not sorted, then:
[As,s_idx] = sort(A);
[~,tmp] = histc(B,As);
idx = s_idx(tmp)

Stephen Politzer-Ahles
Stephen Politzer-Ahles el 8 de Jul. de 2014
Editada: Stephen Politzer-Ahles el 8 de Jul. de 2014
The following should also work for your situation, and just needs one line:
A=[3 4 5 6 7];
B=[6 4 7];
idx = arrayfun( @(x)( find(A==x) ), B );

Junhong YE
Junhong YE el 21 de Jul. de 2014
I think find(ismember(A,B)) would do it.

Categorías

Más información sobre Operating on Diagonal Matrices en Help Center y File Exchange.

Community Treasure Hunt

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

Start Hunting!

Translated by