Discover MakerZone

MATLAB and Simulink resources for Arduino, LEGO, and Raspberry Pi

Learn more

Discover what MATLAB® can do for your career.

Opportunities for recent engineering grads.

Apply Today

To resolve issues starting MATLAB on Mac OS X 10.10 (Yosemite) visit: http://www.mathworks.com/matlabcentral/answers/159016

How to find a vector in a matrix?

Asked by Raymond on 16 Jan 2013

Hi all, I just wonder whether there are Matlab functions which can deal with the problem. Say,

A=[1 1 1 1; ...
   1 1 2 3; ...
   1 2 3 1; ...
   1 1 1 2];
B=[1 2 3]

So B appears twice in A.

I tried ismember, but it finds all the elements of B in A, regardless of the sequence.

Thanks!

1 Comment

Shashank Prasanna on 16 Jan 2013

Just to clarify, you don't want to do this using a for loop? that would be fairly straightforward

Raymond

Tags

Products

No products are associated with this question.

6 Answers

Answer by Matt J on 16 Jan 2013
Accepted answer
    A=[1 1 1 1; 1 1 2 3; 1 2 3 1; 1 1 1 2];
    B=[1 2 3]; 
    [j,i]=ind2sub(fliplr(size(A)),  strfind(reshape(A.',1,[]),B).' );
    >> [i,j]
    ans =
         2     2
         3     1

0 Comments

Matt J
Answer by Andrei Bobrov on 17 Jan 2013
Edited by Andrei Bobrov on 17 Jan 2013
s = size(B) - 1;
n = size(A) - s;
out = [];
for ii = 1:n(1)
    i1 = ii : ii + s(1);
    for jj = 1:n(2)
        if isequal(A(i1,jj : jj + s(2)),B)
            out = [out;[ii,jj]];
        end
    end
end

0 Comments

Andrei Bobrov
Answer by José-Luis on 16 Jan 2013
A=[1 1 1 1; 1 1 2 3; 1 2 3 1; 1 1 1 2];
B=[1 2 3]; 
isSubStr = @(x,y) ~isempty(strfind(x,y));
getStr = @(x) sprintf('%d',x);
numVals = size(A,2);
logical_index = arrayfun(@(idx) isSubStr(getStr(A(idx,:)),getStr(B)),1:numVals)';

0 Comments

José-Luis
Answer by Matt J on 16 Jan 2013
Edited by Matt J on 16 Jan 2013
 N=sqrt( conv2(A.^2,ones(size(B)), 'valid' ));
[i,j]=find(abs( conv2(A,fliplr(B)/norm(B),'valid')./N - 1)<=1e-6)

0 Comments

Matt J
Answer by Roger Stafford on 17 Jan 2013

Another way:

 [m,n] = size(A);
 k = length(B(:));
 p = hankel(1:k,k:n);
 f = find(all(bsxfun(@eq,reshape(A(:,p).',k,n-k+1,m),B(:)),1));
 [c,r] = ind2sub([n-k+1,m],f);

where c gives the column indices and r the row indices in A where a match with B begins. In your example these would be

 r   c
 -   -
 2   2
 3   1

0 Comments

Roger Stafford
Answer by Raymond on 17 Jan 2013

Thanks all! All the solutions work, but Matt's looks simpler and more efficient.

I want to avoid for loops since I have to deal with big matrix.

2 Comments

Sean de Wolski on 17 Jan 2013

@Raymond, The for-loops will smoke ind2sub() any day of the week for large arrays. ind2sub() is convenient not fast.

Matt J on 17 Jan 2013

Don't know what ind2sub has to do with anything, but the for-loop approach is definitely not faster:

    A=[1 1 1 1; 1 1 2 3; 1 2 3 1; 1 1 1 2];
    B=[1 2 3];
    A(10000,1)=0;
    tic;
        [j,i]=ind2sub(fliplr(size(A)),  strfind(reshape(A.',1,[]),B).' );
    toc
    %Elapsed time is 0.001019 seconds. 

####################

     tic
    s = size(B) - 1;
    n = size(A) - s;
    out = [];
    for ii = 1:n(1)
        i1 = ii : ii + s(1);
        for jj = 1:n(2)
            if isequal(A(i1,jj : jj + s(2)),B)
                out = [out;[ii,jj]];
            end
        end
    end
    toc;
    %Elapsed time is 0.039563 seconds.
Raymond

Contact us