gusucode.com > symbolic工具箱matlab源码程序 > symbolic/private/symIsMember.m
function varargout = symIsMember(varargin) %ISMEMBER True for set member. % LIA = ISMEMBER(A,B) for arrays A and B returns an array of the same % size as A containing true where the elements of A are in B and false % otherwise. % % LIA = ISMEMBER(A,B,'rows') for matrices A and B with the same number % of columns, returns a vector containing true where the rows of A are % also rows of B and false otherwise. % % [LIA,LOCB] = ISMEMBER(A,B) also returns an array LOCB containing the % lowest absolute index in B for each element in A which is a member of % B and 0 if there is no such index. % % [LIA,LOCB] = ISMEMBER(A,B,'rows') also returns a vector LOCB containing % the lowest absolute index in B for each row in A which is a member % of B and 0 if there is no such index. % % The behavior of ISMEMBER has changed. This includes: % - occurrence of indices in LOCB switched from highest to lowest % - tighter restrictions on combinations of classes % % If this change in behavior has adversely affected your code, you may % preserve the previous behavior with: % % [LIA,LOCB] = ISMEMBER(A,B,'legacy') % [LIA,LOCB] = ISMEMBER(A,B,'rows','legacy') % % Examples: % % a = [9 9 8 8 7 7 7 6 6 6 5 5 4 4 2 1 1 1] % b = [1 1 1 3 3 3 3 3 4 4 4 4 4 9 9 9] % % [lia1,locb1] = ismember(a,b) % % returns % lia1 = [1 1 0 0 0 0 0 0 0 0 0 0 1 1 0 1 1 1] % locb1 = [16 16 0 0 0 0 0 0 0 0 0 0 13 13 0 3 3 3] % % [lia2,locb2] = ismember(a,b,'R2012a') % % returns % lia2 = [1 1 0 0 0 0 0 0 0 0 0 0 1 1 0 1 1 1] % locb2 = [14 14 0 0 0 0 0 0 0 0 0 0 9 9 0 1 1 1] % % [lia,locb] = ismember([1 NaN 2 3],[3 4 NaN 1]) % % NaNs compare as not equal, so this returns % lia = [1 0 0 1], locb = [4 0 0 1] % % Class support for inputs A and B, where A and B must be of the same % class unless stated otherwise: % - logical, char, all numeric classes (may combine with double arrays) % - cell arrays of strings (may combine with char arrays) % -- 'rows' option is not supported for cell arrays % - objects with methods SORT (SORTROWS for the 'rows' option), EQ and NE % -- including heterogeneous arrays derived from the same root class % % See also UNIQUE, UNION, INTERSECT, SETDIFF, SETXOR, SORT, SORTROWS. % Copyright 1984-2012 The MathWorks, Inc. % Determine the number of outputs requested. if nargout == 0 nlhs = 1; else nlhs = nargout; end narginchk(2,4); nrhs = nargin; if nrhs == 2 [varargout{1:nlhs}] = ismemberR2012a(varargin{:}); else % acceptable combinations, with optional inputs denoted in [] % ismember(A,B, ['rows'], ['legacy'/'R2012a']) nflagvals = 3; flagvals = {'rows' 'legacy' 'R2012a'}; % When a flag is found, note the index into varargin where it was found flaginds = zeros(1,nflagvals); for i = 3:nrhs flag = varargin{i}; foundflag = strcmpi(flag,flagvals); if ~any(foundflag) if ischar(flag) error(message('MATLAB:ISMEMBER:UnknownFlag',flag)); else error(message('MATLAB:ISMEMBER:UnknownInput')); end end % Only 1 occurrence of each allowed flag value if flaginds(foundflag) error(message('MATLAB:ISMEMBER:RepeatedFlag',flag)); end flaginds(foundflag) = i; end % Only 1 of each of the paired flags if flaginds(2) && flaginds(3) error(message('MATLAB:ISMEMBER:BehaviorConflict')) end % 'legacy' and 'R2012a' flags must be trailing if flaginds(2) && flaginds(2)~=nrhs error(message('MATLAB:ISMEMBER:LegacyTrailing')) end if flaginds(3) && flaginds(3)~=nrhs error(message('MATLAB:ISMEMBER:R2012aTrailing')) end if flaginds(3) % trailing 'R2012a' specified [varargout{1:nlhs}] = ismemberR2012a(varargin{1:2},logical(flaginds(1))); elseif flaginds(2) % trailing 'legacy' specified [varargout{1:nlhs}] = ismemberlegacy(varargin{1:2},logical(flaginds(1))); else % 'R2012a' (default behavior) [varargout{1:nlhs}] = ismemberR2012a(varargin{1:2},logical(flaginds(1))); end end end function [tf,loc] = ismemberlegacy(a,s,isrows) % 'legacy' flag implementation if nargin == 3 && isrows flag = 'rows'; else flag = []; end numelA = numel(a); numelS = numel(s); nOut = nargout; % Handle objects that cannot be converted to doubles if isempty(flag) % Handle empty arrays and scalars. if numelA == 0 || numelS <= 1 if (numelA == 0 || numelS == 0) tf = false(size(a)); loc = zeros(size(a)); return % Scalar A handled below. % Scalar S: find which elements of A are equal to S. elseif numelS == 1 tf = logical(a == s); if nOut > 1 % Use DOUBLE to convert logical "1" index to double "1" index. loc = double(tf); end return end else % General handling. % Use FIND method for very small sizes of the input vector to avoid SORT. scalarcut = 5; if numelA <= scalarcut tf = false(size(a)); loc = zeros(size(a)); if nOut <= 1 for i=1:numelA tf(i) = any(a(i)==s); % ANY returns logical. end else for i=1:numelA found = find(a(i)==s); % FIND returns indices for LOC. if ~isempty(found) tf(i) = 1; loc(i) = found(end); end end end else % Duplicates within the sets are eliminated [au,~,an] = unique(a(:),'legacy'); if nOut <= 1 su = unique(s(:),'legacy'); else [su,sm] = unique(s(:),'legacy'); end % Sort the unique elements of A and S, duplicate entries are adjacent [c,ndx] = sort([au;su]); % Find matching entries d = c(1:end-1)==c(2:end); % d indicates matching entries in 2-D d = find(d); % Finds the index of matching entries ndx1 = ndx(d); % NDX1 are locations of repeats in C if nOut <= 1 tf = ismember(an,ndx1,'legacy'); % Find repeats among original list else szau = size(au,1); [tf,loc] = ismember(an,ndx1,'legacy'); % Find loc by using given indices newd = d(loc(tf)); % NEWD is D for non-unique A where = sm(ndx(newd+1)-szau); % Index values of SU through UNIQUE loc(tf) = where; % Return last occurrence of A within S end end tf = reshape(tf,size(a)); if nOut > 1 loc = reshape(loc,size(a)); end end else % 'rows' case rowsA = size(a,1); colsA = size(a,2); %#ok<NASGU> rowsS = size(s,1); colsS = size(s,2); %#ok<NASGU> % Automatically pad strings with spaces if size(a,2)~=size(s,2) && ~isempty(a) && ~isempty(s) error(message('MATLAB:ISMEMBER:AandBColnumAgree')); end % Empty check for 'rows'. if rowsA == 0 || rowsS == 0 if (isempty(a) || isempty(s)) tf = false(rowsA,1); loc = zeros(rowsA,1); return end end % Duplicates within the sets are eliminated if (rowsA == 1) au = repmat(a,rowsS,1); d = logical(au(1:end,:)==s(1:end,:)); d = all(d,2); tf = any(d); if nOut > 1 if tf loc = find(d, 1, 'last'); else loc = 0; end end return; end [au,~,an] = unique(a,'rows','legacy'); if nOut <= 1 su = unique(s,'rows','legacy'); else [su,sm] = unique(s,'rows','legacy'); end % Sort the unique elements of A and S, duplicate entries are adjacent [c,ndx] = sortrows([au;su]); % Find matching entries d = c(1:end-1,:)==c(2:end,:); % d indicates matching entries in 2-D d = find(all(d,2)); % Finds the index of matching entries ndx1 = ndx(d); % NDX1 are locations of repeats in C if nOut <= 1 tf = ismember(an,ndx1,'legacy'); % Find repeats among original list else szau = size(au,1); [tf,loc] = ismember(an,ndx1,'legacy'); % Find loc by using given indices newd = d(loc(tf)); % NEWD is D for non-unique A where = sm(ndx(newd+1)-szau); % Index values of SU through UNIQUE loc(tf) = where; % Return last occurrence of A within S end end end function [lia,locb] = ismemberR2012a(a,b,options) % 'R2012a' flag implementation % Error check flag if nargin == 2 byrow = false; else byrow = options > 0; end classFlag = true; %#ok<NASGU> numelA = numel(a); %#ok<NASGU> if ~byrow % Duplicates within the sets are eliminated if isscalar(a) || isscalar(b) ab = [a(:);b(:)]; sort(ab(1)); numa = numel(a); lia = logical(ab(1:numa)==ab(1+numa:end)); if ~any(lia) lia = false(size(a)); locb = zeros(size(a)); return end if ~isscalar(b) locb = find(lia); locb = locb(1); lia = any(lia); else locb = double(lia); end else % Duplicates within the sets are eliminated [uA,~,icA] = unique(a(:),'sorted'); if nargout <= 1 uB = unique(b(:),'sorted'); else [uB,ib] = unique(b(:),'sorted'); end % Sort the unique elements of A and B, duplicate entries are adjacent [sortuAuB,IndSortuAuB] = sort([uA;uB]); % Find matching entries d = logical(sortuAuB(1:end-1)==sortuAuB(2:end)); % d indicates the indices matching entries ndx1 = IndSortuAuB(d); % NDX1 are locations of repeats in C if nargout <= 1 lia = ismember(icA,ndx1,'R2012a'); % Find repeats among original list else szuA = size(uA,1); d = find(d); [lia,locb] = ismember(icA,ndx1,'R2012a'); % Find locb by using given indices newd = d(locb(lia)); % NEWD is D for non-unique A where = ib(IndSortuAuB(newd+1)-szuA); % Index values of uB through UNIQUE locb(lia) = where; % Return first or last occurrence of A within B end end lia = reshape(lia,size(a)); if nargout > 1 locb = reshape(locb,size(a)); end else % 'rows' case if ~(ismatrix(a) && ismatrix(b)) error(message('MATLAB:ISMEMBER:NotAMatrix')); end [rowsA,colsA] = size(a); [rowsB,colsB] = size(b); % Automatically pad strings with spaces if colsA ~= colsB error(message('MATLAB:ISMEMBER:AandBColnumAgree')); end % Empty check for 'rows'. if rowsA == 0 || rowsB == 0 lia = false(rowsA,1); locb = zeros(rowsA,1); return end % General handling for 'rows'. % Duplicates within the sets are eliminated if (rowsA == 1) uA = repmat(a,rowsB,1); d = logical(uA(1:end,:)==b(1:end,:)); d = all(d,2); lia = any(d); if nargout > 1 if lia locb = find(d, 1, 'first'); else locb = 0; end end return; else [uA,~,icA] = unique(a,'rows','sorted'); end if nargout <= 1 uB = unique(b,'rows','sorted'); else [uB,ib] = unique(b,'rows','sorted'); end % Sort the unique elements of A and B, duplicate entries are adjacent [sortuAuB,IndSortuAuB] = sortrows([uA;uB]); % Find matching entries d = logical(sortuAuB(1:end-1,:)==sortuAuB(2:end,:)); % d indicates matching entries d = all(d,2); % Finds the index of matching entries ndx1 = IndSortuAuB(d); % NDX1 are locations of repeats in C if nargout <= 1 lia = ismember(icA,ndx1,'R2012a'); % Find repeats among original list else szuA = size(uA,1); [lia,locb] = ismember(icA,ndx1,'R2012a'); % Find locb by using given indices d = find(d); newd = d(locb(lia)); % NEWD is D for non-unique A where = ib(IndSortuAuB(newd+1)-szuA); % Index values of uB through UNIQUE locb(lia) = where; % Return first or last occurrence of A within B end end end