Finding the indices of the elements of one array in another

606 Ansichten (letzte 30 Tage)
Alan
Alan am 3 Dez. 2011
Kommentiert: David am 18 Jan. 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 Kommentare
Philip
Philip am 26 Sep. 2014
MATLAB supports logical indexing. No need to use "find":
A = A( ismember( A, B ) );
Leandro Coelho
Leandro Coelho am 1 Jul. 2016
Another option: intersect(A,B)

Melden Sie sich an, um zu kommentieren.

Akzeptierte Antwort

Sven
Sven am 3 Dez. 2011
Bearbeitet: MathWorks Support Team am 9 Nov. 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 Kommentare
Alan
Alan am 3 Dez. 2011
I am wondering though if "intersect" and "sort" would be expensive on large arrays.
tc88
tc88 am 22 Aug. 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.

Melden Sie sich an, um zu kommentieren.

Weitere Antworten (6)

Alan
Alan am 3 Dez. 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 Kommentare
Iftikhar Ali
Iftikhar Ali am 18 Okt. 2015
Method 3 has solved my problem, thanks.
David
David am 18 Jan. 2020
Method one also works if there are multiple occurences of B in A. Intersect fails in this case.

Melden Sie sich an, um zu kommentieren.


Alan
Alan am 6 Dez. 2011
Thinking again, I realize that ismember is all I need
[~,idx]=ismember(B,A)
will do it.
  2 Kommentare
normanius
normanius am 9 Okt. 2017
This is by far the best answer!
John Sogade
John Sogade am 2 Jan. 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)).

Melden Sie sich an, um zu kommentieren.


Iftikhar Ali
Iftikhar Ali am 18 Okt. 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 am 3 Dez. 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 am 8 Jul. 2014
Bearbeitet: Stephen Politzer-Ahles am 8 Jul. 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 am 21 Jul. 2014
I think find(ismember(A,B)) would do it.

Kategorien

Mehr zu Operating on Diagonal Matrices finden Sie in Help Center und File Exchange

Community Treasure Hunt

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

Start Hunting!

Translated by