Leba
Leba

Reputation: 109

Row-wise "ismember" without for-loop

I am trying to perform a row-wise "ismember" in MATLAB in order to find out where, in Set, each element of Input is. Here is my work so far.

function lia = ismemberrow(Input, Set)
    lia = false(size(Input)); % Pre-assign the output lia
    for J = 1 : size(Input,1)
        % The J-th row of "lia" is the list of locations of the
        % elements of Input(J,:) in Set
        lia(J,:) = find(ismember(Set, Input(J,:)));
    end
end

For example, if the variables Input and Set are defined as follows

Input = [1 4; 
         4 2; 
         4 3; 
         2 4; 
         1 2; 
         3 2];
Set = [3 2 4 1];

The the output lia of lia = ismemberrow(Input,Set) will be:

lia = [4 3; 
       3 2; 
       3 1; 
       2 3; 
       4 2; 
       1 2];

My function works accurately so far, but this function is called many times in my project so I am thinking of that if I can reduce the for-loop so that it spends less time. May I have some opinions on it?

Upvotes: 3

Views: 371

Answers (3)

gnovice
gnovice

Reputation: 125854

A single call to ismember (no loop necessary) will give you what you want in the second output argument:

>> [~, lia] = ismember(Input, Set)

lia =

     4     3
     3     2
     3     1
     2     3
     4     2
     1     2

Upvotes: 4

rahnema1
rahnema1

Reputation: 15837

If your inputs are positive integers you simply can use indexing

m(Set)=1:numel(Set);
result = m(Input)

If the range of input is large you can use sparse matrix:

s = sparse(Set,1,1:numel(Set));
result = s(Input)

Result:

   4   3
   3   2
   3   1
   2   3
   4   2
   1   2

Upvotes: 1

Luis Mendo
Luis Mendo

Reputation: 112659

I'd go with ismember as in @gnovice's answer. But here are some alternatives, just for the fun of it.

  1. If the values in Input are guaranteed to be in Set:

    [ind, ~] = find(bsxfun(@eq, Set(:), Input(:).'));
    result = reshape(ind, size(Input));
    
  2. If they are not guaranteed to be:

    [ind, val] = max(bsxfun(@eq, Set(:), permute(Input, [3 1 2])));
    result = permute(ind.*val, [2 3 1]);
    

Upvotes: 1

Related Questions