time | Calls | line |
---|
| | 167 | function [c,indA,indC] = uniqueR2012a(a,options)
|
| | 168 | % 'R2012a' flag implementaion
|
| | 169 |
|
| | 170 | % flagvals = {'rows' 'first' 'last' 'sorted' 'stable'};
|
< 0.001 | 15 | 171 | if nargin == 1
|
< 0.001 | 15 | 172 | byrow = false;
|
< 0.001 | 15 | 173 | order = 'sorted';
|
| | 174 | else
|
| | 175 | byrow = (options(1) > 0);
|
| | 176 | if options(5) > 0
|
| | 177 | order = 'stable';
|
| | 178 | elseif options(3) > 0
|
| | 179 | order = 'last';
|
| | 180 | else % if options(4) > 0 || options(2) || sum(options(2:5) == 0)
|
| | 181 | order = 'sorted'; %'first' and 'sorted' do the same thing
|
| | 182 | end
|
< 0.001 | 15 | 183 | end
|
| | 184 |
|
| | 185 | % Determine if A is a row vector.
|
< 0.001 | 15 | 186 | rowvec = isrow(a);
|
| | 187 |
|
< 0.001 | 15 | 188 | if ~byrow || iscolumn(a) % default case
|
| | 189 |
|
| | 190 | % Convert to column
|
< 0.001 | 15 | 191 | a = a(:);
|
< 0.001 | 15 | 192 | numelA = numel(a);
|
| | 193 |
|
| | 194 | % Sort A and get the indices if needed.
|
< 0.001 | 15 | 195 | isSortedA = false;
|
< 0.001 | 15 | 196 | if isnumeric(a) && ~isobject(a)
|
< 0.001 | 15 | 197 | isSortedA = issorted(a);
|
< 0.001 | 15 | 198 | end
|
| | 199 |
|
< 0.001 | 15 | 200 | if nargout > 1 || strcmp(order, 'stable')
|
< 0.001 | 15 | 201 | if isSortedA
|
| | 202 | sortA = a;
|
| | 203 | indSortA = (1:numelA)';
|
< 0.001 | 15 | 204 | else
|
0.004 | 15 | 205 | [sortA,indSortA] = sort(a);
|
< 0.001 | 15 | 206 | end
|
| | 207 | else
|
| | 208 | if isSortedA
|
| | 209 | sortA = a;
|
| | 210 | else
|
| | 211 | sortA = sort(a);
|
| | 212 | end
|
< 0.001 | 15 | 213 | end
|
| | 214 |
|
| | 215 | % groupsSortA indicates the location of non-matching entries.
|
< 0.001 | 15 | 216 | if isnumeric(sortA) && (numelA > 1)
|
< 0.001 | 15 | 217 | dSortA = diff(sortA);
|
< 0.001 | 15 | 218 | if (isnan(dSortA(1)) || isnan(dSortA(numelA-1)))
|
| | 219 | groupsSortA = sortA(1:numelA-1) ~= sortA(2:numelA);
|
< 0.001 | 15 | 220 | else
|
< 0.001 | 15 | 221 | groupsSortA = dSortA ~= 0;
|
< 0.001 | 15 | 222 | end
|
| | 223 |
|
| | 224 | else
|
| | 225 | groupsSortA = sortA(1:numelA-1) ~= sortA(2:numelA);
|
< 0.001 | 15 | 226 | end
|
| | 227 |
|
< 0.001 | 15 | 228 | if (numelA ~= 0)
|
< 0.001 | 15 | 229 | if strcmp(order, 'last')
|
| | 230 | groupsSortA = [groupsSortA; true]; % Final element is always a member of unique list.
|
< 0.001 | 15 | 231 | else % if (strcmp(order, 'sorted') || strcmp(order, 'stable'))
|
< 0.001 | 15 | 232 | groupsSortA = [true; groupsSortA]; % First element is always a member of unique list.
|
< 0.001 | 15 | 233 | end
|
| | 234 | else
|
| | 235 | groupsSortA = zeros(0,1);
|
< 0.001 | 15 | 236 | end
|
| | 237 |
|
| | 238 | % Extract unique elements.
|
< 0.001 | 15 | 239 | if strcmp(order, 'stable')
|
| | 240 | invIndSortA = indSortA;
|
| | 241 | invIndSortA(invIndSortA) = 1:numelA; % Find inverse permutation.
|
| | 242 | logIndA = groupsSortA(invIndSortA); % Create new logical by indexing into groupsSortA.
|
| | 243 | c = a(logIndA); % Create unique list by indexing into unsorted a.
|
< 0.001 | 15 | 244 | else
|
< 0.001 | 15 | 245 | c = sortA(groupsSortA); % Create unique list by indexing into sorted list.
|
< 0.001 | 15 | 246 | end
|
| | 247 |
|
| | 248 | % Find indA.
|
< 0.001 | 15 | 249 | if nargout > 1
|
< 0.001 | 15 | 250 | if strcmp(order, 'stable')
|
| | 251 | indA = find(logIndA); % Find the indices of the unsorted logical.
|
< 0.001 | 15 | 252 | else
|
< 0.001 | 15 | 253 | indA = indSortA(groupsSortA); % Find the indices of the sorted logical.
|
< 0.001 | 15 | 254 | end
|
< 0.001 | 15 | 255 | end
|
| | 256 |
|
| | 257 | % Find indC.
|
< 0.001 | 15 | 258 | if nargout == 3
|
< 0.001 | 15 | 259 | groupsSortA = full(groupsSortA);
|
< 0.001 | 15 | 260 | if numelA == 0
|
| | 261 | indC = zeros(0,1);
|
< 0.001 | 15 | 262 | else
|
< 0.001 | 15 | 263 | switch order
|
< 0.001 | 15 | 264 | case 'last'
|
| | 265 | indC = cumsum([1;groupsSortA(1:end-1)]); % Lists position, starting at 1.
|
| | 266 | indC(indSortA) = indC; % Re-reference indC to indexing of sortA.
|
< 0.001 | 15 | 267 | case 'sorted'
|
< 0.001 | 15 | 268 | indC = cumsum(groupsSortA); % Lists position, starting at 1.
|
0.002 | 15 | 269 | indC(indSortA) = indC; % Re-reference indC to indexing of sortA.
|
| | 270 | otherwise % 'stable'
|
| | 271 | [~,indSortC] = sort(c); % Sort C to get index.
|
| | 272 |
|
| | 273 | lengthGroupsSortA = diff(find([groupsSortA; true])); % Determine how many of each of the above indices there are in IC.
|
| | 274 |
|
| | 275 | diffIndSortC = diff(indSortC); % Get the correct amount of each index.
|
| | 276 | diffIndSortC = [indSortC(1); diffIndSortC];
|
| | 277 |
|
| | 278 | indLengthGroupsSortA = cumsum([1; lengthGroupsSortA]);
|
| | 279 | indLengthGroupsSortA(end) = [];
|
| | 280 |
|
| | 281 | indCOrderedBySortA(indLengthGroupsSortA,1) = diffIndSortC; % Since indCOrderedBySortA is not already established as a column,
|
| | 282 | if sum(lengthGroupsSortA) ~= length(indCOrderedBySortA) % This is false if all the elements in A originally were unique and
|
| | 283 | indCOrderedBySortA(sum(lengthGroupsSortA),1) = 0; % true if the original A had duplicates.
|
| | 284 | end
|
| | 285 |
|
| | 286 | indCOrderedBySortA = cumsum(indCOrderedBySortA);
|
| | 287 | indC = indCOrderedBySortA(invIndSortA); % Reorder the list of indices to the unsorted order.
|
< 0.001 | 15 | 288 | end
|
< 0.001 | 15 | 289 | end
|
< 0.001 | 15 | 290 | end
|
| | 291 |
|
| | 292 | % If A is row vector, return C as row vector.
|
< 0.001 | 15 | 293 | if rowvec
|
| | 294 | c = c.';
|
| | 295 | end
|
| | 296 |
|
| | 297 | else % 'rows' case
|
| | 298 | if ~ismatrix(a)
|
| | 299 | error(message('MATLAB:UNIQUE:ANotAMatrix'));
|
| | 300 | end
|
| | 301 |
|
| | 302 | numRows = size(a,1);
|
| | 303 | numCols = size(a,2);
|
| | 304 |
|
| | 305 | % Sort A and get the indices if needed.
|
| | 306 | isSortedA = false;
|
| | 307 | if isnumeric(a) && ~isobject(a)
|
| | 308 | isSortedA = issortedrows(a);
|
| | 309 | end
|
| | 310 |
|
| | 311 | if nargout > 1 || strcmp(order, 'stable')
|
| | 312 | if isSortedA
|
| | 313 | sortA = a;
|
| | 314 | indSortA = (1:numRows)';
|
| | 315 | else
|
| | 316 | [sortA,indSortA] = sortrows(a);
|
| | 317 | end
|
| | 318 | else
|
| | 319 | if isSortedA
|
| | 320 | sortA = a;
|
| | 321 | else
|
| | 322 | sortA = sortrows(a);
|
| | 323 | end
|
| | 324 | end
|
| | 325 |
|
| | 326 | % groupsSortA indicates the location of non-matching entries.
|
| | 327 | groupsSortA = sortA(1:numRows-1,:) ~= sortA(2:numRows,:);
|
| | 328 | groupsSortA = any(groupsSortA,2);
|
| | 329 | if (numRows ~=0)
|
| | 330 | if strcmp(order, 'last')
|
| | 331 | groupsSortA = [groupsSortA; true]; % Final row is always member of unique list.
|
| | 332 | else % if (strcmp(order, 'sorted') || strcmp(order, 'stable'))
|
| | 333 | groupsSortA = [true; groupsSortA]; % First row is always a member of unique list.
|
| | 334 | end
|
| | 335 | end
|
| | 336 |
|
| | 337 | % Extract Unique elements.
|
| | 338 | if strcmp(order, 'stable')
|
| | 339 | invIndSortA = indSortA;
|
| | 340 | invIndSortA(invIndSortA) = 1:numRows; % Find the inverse permutation of indSortA.
|
| | 341 | logIndA = groupsSortA(invIndSortA); % Create new logical by indexing into groupsSortA.
|
| | 342 | c = a(logIndA,:); % Create unique list by indexing into unsorted a.
|
| | 343 | else
|
| | 344 | c = sortA(groupsSortA,:); % Create unique list by indexing into sorted list.
|
| | 345 | end
|
| | 346 |
|
| | 347 | % Find indA.
|
| | 348 | if nargout > 1
|
| | 349 | if strcmp(order, 'stable')
|
| | 350 | indA = find(logIndA); % Find the indices of the unsorted logical.
|
| | 351 | else
|
| | 352 | indA = indSortA(groupsSortA); % Find the indices of the sorted logical.
|
| | 353 | end
|
| | 354 | end
|
| | 355 |
|
| | 356 | % Find indC.
|
| | 357 | if nargout == 3
|
| | 358 | groupsSortA = full(groupsSortA);
|
| | 359 | switch order
|
| | 360 | case 'last'
|
| | 361 | if (numRows == 0)
|
| | 362 | indC = cumsum(groupsSortA); % Empty A - use all of groupsSortA.
|
| | 363 | indC(indSortA) = indC;
|
| | 364 | else
|
| | 365 | indC = cumsum([1;full(groupsSortA(1:end-1))]); % Lists position, starting at 1.
|
| | 366 | indC(indSortA) = indC; % Re-reference indC to indexing of sortA.
|
| | 367 | end
|
| | 368 | case 'sorted'
|
| | 369 | indC = cumsum(groupsSortA); % Lists position, starting at 1.
|
| | 370 | indC(indSortA) = indC; % Re-reference indC to indexing of sortA.
|
| | 371 | otherwise % 'stable'
|
| | 372 | if numCols == 0
|
| | 373 | indC = ones(numRows,1); % For 'stable' ensure that empty A gives correct size and shape.
|
| | 374 | elseif numRows == 0
|
| | 375 | indC = zeros(0,1);
|
| | 376 | else
|
| | 377 | [~,indSortC] = sortrows(c); % Sort C to get index.
|
| | 378 |
|
| | 379 | lengthGroupsSortA = diff(find([groupsSortA; true])); % Determine how many of each of the above indices there are in IC.
|
| | 380 |
|
| | 381 | diffIndSortC = diff(indSortC);
|
| | 382 | diffIndSortC = [indSortC(1); diffIndSortC];
|
| | 383 |
|
| | 384 | indLengthGroupsSortA = cumsum([1; lengthGroupsSortA]); % Get the correct amount of each index.
|
| | 385 | indLengthGroupsSortA(end) = [];
|
| | 386 |
|
| | 387 | indCOrderedBySortA(indLengthGroupsSortA,1) = diffIndSortC; % Since indCOrderedBySortA is not already established as a column,
|
| | 388 |
|
| | 389 | if sum(lengthGroupsSortA) ~= length(indCOrderedBySortA)
|
| | 390 | indCOrderedBySortA(sum(lengthGroupsSortA),1) = 0;
|
| | 391 | end
|
| | 392 |
|
| | 393 | indCOrderedBySortA = cumsum(indCOrderedBySortA);
|
| | 394 | indC = indCOrderedBySortA(invIndSortA); % Reorder the list of indices to the unsorted order.
|
| | 395 | end
|
| | 396 | end
|
| | 397 | end
|
< 0.001 | 15 | 398 | end
|
< 0.001 | 15 | 399 | end
|
Other subfunctions in this file are not included in this listing.