1 view (last 30 days)

Show older comments

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.

Jan
on 23 Jul 2021

Edited: Jan
on 23 Jul 2021

You want to get a logical vector for each element, which is TRUE for the matching elements. Then this is efficient:

a = [1 2 3 3 5 6 6];

b = [1 2 3 5 6];

match = (b.' == a)

This works with auto-expanding since R2016b. For older Matlab versions:

match = bsxfun(@eq, b.', a)

If you want the indices instead, a loop is nice and efficient (I assume, you have this already, but maybe another user might be interested):

indices = cell(size(b)); % Pre-allocate

for k = 1:numel(b)

indices{k} = find(b(k) == a);

% This would waste time to create a temporary cell:

% indices(k) = {find(b(k) == a)};

end

Chunru
on 23 Jul 2021

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

Jan
on 23 Jul 2021

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.

per isakson
on 23 Jul 2021

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}

Jan
on 23 Jul 2021

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

Start Hunting!