function TF = matchrow(M,S)
% MATCHROW - match elements in the rows of the matrix
%
% TF = MATCHROW(M,S) returns a column vector containing a logical 1 (true)
% where the rows of M contain (in any order) all the numbers of S and 0 otherwise.
% If a value is present N times in S, it has to be present at least N
% times in these rows of M as well.
% M and S can be a cell array of strings.
%
% Examples:
% M = [ 1 2 3 4 5 ; 1 2 2 4 3; 1 3 4 4 3 ; 3 2 4 2 5 ; 1 4 3 2 4 ] ;
% Q = matchrow(M,[1 2 4]) % -> [1 ; 1 ; 0 ; 0 ; 1] ;
% M(Q,:) % -> 1 2 3 4 5
% % 1 2 2 4 3
% % 1 4 3 2 4
%
% Q = matchrow(M,[1 2 4 4])
% M(Q,:) % -> 1 4 3 2 4
%
% Q = matchrow({'a','X','c','Y'; 'a','X','Y','d' ;
% 'b','X','d','e'},{'X','Y'}) % -> [1 ; 1 ; 0] ;
%
% A = rand(999,999) ;
% x = 27 ;
% tic
% find(matchrow(A,A(x,:))) == x % -> true!
% toc
%
% MATCHROW is vectorized and pretty quick ...
%
% See also FIND, ISMEMBER
% for Matlab R13
% version 1.1 (may 2008)
% (c) Jos van der Geest
% email: jos@jasen.nl
% History
% 1.0 Created: apr 2007, inspired by a post on CSSM
% 1.1 (may 2008) - fixed small error when numel(S) > size(M,1)
% argument checking: are there enough
error(nargchk(2,2,nargin)) ;
% does M have the proper dimensions
if ndims(M) ~= 2,
error ('Matrix argument M should be a 2D array.') ;
end
if iscell(M),
% for a cell array of strings, convert to numbers first
try
% cell arrays of mixed tpes (numbers and strings) will error here
uM = unique(M) ;
[M,M] = ismember(M,uM) ;
[S,S] = ismember(S,uM) ;
catch
error('Cell input must be a cell array of strings.') ;
end
end
nS = numel(S) ;
if nS == 1,
% trivial case
% look for the presence of the number in each row
TF = any(M==S,2) ;
elseif nS > size(M,2),
% another trivial case
% there are to many numbers to fit in a row
warning('findrow:SizeTooLarge','Row exceeds matrix size') ;
TF = false(size(M,1),1) ;
else
% now we have to do some work
uS = unique(S(:)) ; % what are the unique elements in S
nuS = numel(uS) ; % and how many are there
nS = histc(S(:),uS) ; % and how many times is each element present
% Use ismember to look if elements in uS are present in M
[M,M] = ismember(M,uS) ;
% Count the number of occurences of each unique element in M
N = histc(M.',1:nuS) ; % Note that histc operates on columns, so transpose first
% subtract the number each numbers should at least occur
N = N - repmat(nS,1,size(N,2)) ;
% if all N are >= 0, than each number in S is present enough times in M
TF = ~any(N<0,1).' ;
end