check ismember for each element individually
이전 댓글 표시
Hello all,
I wonder if there is any smart way checking the indices of every individual elements in an array, in another array.
For example,given an input
a=[ 1 2 3 3 5 6 6];
b=[1 2 3 5 6];
I want to check where is each element of b is located in a
for example: for b(1), the location in a) would be:
[1 0 0 0 0 0 0]
%or
a(1)
for b(3), it then would be:
[0 0 1 1 0 0 0]
%or
a(3,4)
of course I can do it using For loop, for speed reason I need to avoid it.
채택된 답변
추가 답변 (2개)
Doc ismember to see if it meets your requirement:
a=[ 1 2 3 3 5 6 6];
b=[1 2 3 5 6];
[Lib, Loca] = ismember(b, a)
a(Loca) % Loca is the the location of the first appearance of b in a
댓글 수: 3
Xingda Chen
2021년 7월 23일
%% arrayfun
a=[ 1 2 3 3 5 6 6];
b=[1 2 3 5 6];
a = randi(100, 1e6, 1);
b = randi(100, 1e3, 1);
tic
cac = arrayfun( @(ii) find(a==ii), b, 'uni',false );
toc
% Elapsed time is 1.798082 seconds.
%% for loop
tic
cac1 = cell(length(b), 1);
for i=1:length(b)
cac1{i} = find(a==b(i));
end
toc
% Elapsed time is 1.571855 seconds.
%% ismember
% This is fastest.
% it use sort (faster) and stop when 1st appearance is found
tic
[Lib, Loca] = ismember(b, a);
toc
%% array expansion, Jan's answer below
tic
match = (b.' == a)';
toc
Thanks for the useful speed comparison. arrayfun is 10% slower than a loop. That ismember is much faster with its binary search is interesting, but it replies a different result.
In your code for the array expansion method, 60% are spent in the final transposition, which can be omitted:
a = randi(100, 1e6, 1);
b = randi(100, 1e3, 1);
tic
match = (b.' == a).';
toc
% Elapsed time is 1.836326 seconds. (i7, Matlab R2018b)
tic
match = (b.' == a);
toc
% Elapsed time is 0.642080 seconds.
tic
match = (b == a.');
toc
% Elapsed time is 0.553570 seconds.
And if you store the rows of the output in a cell:
tic
cac1 = cell(length(b), 1);
for i=1:length(b)
cac1{i} = (a==b(i)); % Without FIND
end
toc
% Elapsed time is 0.528209 seconds.
By the way: Matlab R2009a:
% Elapsed time is 3.368870 seconds.
% Elapsed time is 1.358478 seconds.
% Elapsed time is 1.219993 seconds.
The function arrayfun() does the trick (i.e. hides the foor-loop)
a=[ 1 2 3 3 5 6 6];
b=[1 2 3 5 6];
cac = arrayfun( @(ii) find(a==ii), b, 'uni',false )
cac{3}
댓글 수: 5
Xingda Chen
2021년 7월 23일
Image Analyst
2021년 7월 23일
편집: Image Analyst
2021년 7월 23일
For loops are fast - almost as fast as vectorized (depending on the operations) and sometimes faster. Run the attached demo to see:
Vectorized won 26 times out of 1000 = 2.6%.
For loop won 974 times out of 1000 = 97.40%.
The average time for the vectorized method = 4.5891e-06.
The average time for the for loop method = 4.1571e-06.
I did a million comparisons and the difference was less than a microsecond. Just how much speed do you need? How big are your arrays?
Xingda Chen
2021년 7월 23일
Jan
2021년 7월 23일
@Chunru: "Loop in newer matlab is no longer the enemy of speed." I can confirm this. In addition for loops tend to be easier to write, read and maintain. By the way, "newer" means the Matlab version, which has introduced the JIT acceleration for loops, and this was Matlab R6.5, so the rumor of slow loops is outdated for over 20 years now.
카테고리
도움말 센터 및 File Exchange에서 Loops and Conditional Statements에 대해 자세히 알아보기
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!