📄 unique.m
字号:
function [b,ndx,pos] = unique(a,flag)
%UNIQUE Set unique.
% UNIQUE(A) for the array A returns the same values as in A but
% with no repetitions. A will also be sorted. A can be a cell
% array of strings.
%
% UNIQUE(A,'rows') for the matrix A returns the unique rows of A.
%
% [B,I,J] = UNIQUE(...) also returns index vectors I and J such
% that B = A(I) and A = B(J) (or B = A(I,:) and A = B(J,:)).
%
% See also UNION, INTERSECT, SETDIFF, SETXOR, ISMEMBER.
% Copyright 1984-2002 The MathWorks, Inc.
% $Revision: 1.24 $ $Date: 2002/02/25 09:40:00 $
% Cell array implementation in @cell/unique.m
nIn = nargin;
if nIn < 1
error('Not enough input arguments.');
elseif nIn > 2
error('Too many input arguments.');
end
if nIn == 1
flag = [];
end
rows = size(a,1);
cols = size(a,2);
rowvec = (rows == 1) && (cols > 1);
numelA = prod(size(a));
nOut = nargout;
if isempty(flag)
% Handle empty: no elements.
if (numelA == 0)
% Predefine b to be of the correct type.
b = a([]);
if max(size(a)) > 0
b = reshape(b,0,1);
ndx = zeros(0,1);
pos = zeros(0,1);
else
ndx = [];
pos = [];
end
return
elseif (numelA == 1)
% Scalar A: return the existing value of A.
b = a; ndx = 1; pos = 1;
return
% General handling.
else
% Convert to columns
a = a(:);
% Convert to double array for purposes of faster sorting.
% Additionally, UNIQUE calls DIFF, which requires double input.
whichclass = class(a);
isdouble = strcmp(whichclass,'double');
if ~isdouble
a = double(a);
end
% Sort if unsorted. Only check this for long lists.
checksortcut = 1000;
if numelA <= checksortcut || ~(issorted(a))
if nOut <= 1
b = sort(a);
else
[b,ndx] = sort(a);
end
else
b = a;
if nOut > 1
ndx = (1:numelA)'; % If presorted, indices are 1,2,3,...
end
end
% d indicates the location of non-matching entries.
db = diff(b);
% Since DIFF returns NaN in both Inf and NaN cases,
% use slower method of detection if NaN's detected in DIFF(b).
% After sort, Infs or NaNs will be at ends of list only.
if (isnan(db(1)) || isnan(db(numelA-1)))
d = b(1:numelA-1) ~= b(2:numelA);
else
d = db ~= 0;
end
d(numelA,1) = 1; % Final element is always member of unique list.
b = b(d); % Create unique list by indexing into sorted list.
if nOut == 3
pos = cumsum([1;full(d)]); % Lists position, starting at 1.
pos(numelA+1) = []; % Remove extra element introduced by d.
pos(ndx) = pos; % Re-reference POS to indexing of SORT.
end
% Create indices if needed.
if nOut > 1
ndx = ndx(d);
end
% Re-convert to correct output data type using FEVAL.
if ~isdouble
b = feval(whichclass,b);
end
end
% If row vector, return as row vector.
if rowvec
b = b.';
if nOut > 1
ndx = ndx.';
if nOut > 2
pos = pos.';
end
end
end
else % 'rows' case
if ~strcmpi(flag,'rows')
error('Unknown flag.');
end
% Handle empty: no rows.
if (rows == 0)
% Predefine b to be of the correct type.
b = a([]);
ndx = [];
pos = [];
b = reshape(b,0,cols);
if cols > 0
ndx = reshape(ndx,0,1);
end
return
% Handle scalar: one row.
elseif (rows == 1)
b = a; ndx = 1; pos = 1;
return
end
% General handling.
% Conversion to double not done: SORTROWS is slower for doubles
% than other types.
if nOut > 1
[b,ndx] = sortrows(a);
else
b = sortrows(a);
end
% d indicates the location of non-matching entries.
d = b(1:rows-1,:)~=b(2:rows,:);
% d = 1 if differences between rows. d = 0 if the rows are equal.
d = any(d,2);
d(rows,1) = 1; % Final row is always member of unique list.
b = b(d,:); % Create unique list by indexing into sorted list.
% Create position mapping vector using CUMSUM.
if nOut == 3
pos = cumsum([1;full(d)]); % Lists position, starting at 1.
pos(rows+1) = []; % Remove extra element introduced by d.
pos(ndx) = pos; % Re-reference POS to indexing of SORT.
end
% Create indices if needed.
if nOut > 1
ndx = ndx(d);
end
end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -