1 | function [c,ia] = setdiff(a,b,flag) |
---|
2 | %SETDIFF Set difference. |
---|
3 | % SETDIFF(A,B) when A and B are vectors returns the values |
---|
4 | % in A that are not in B. The result will be sorted. A and B |
---|
5 | % can be cell arrays of strings. |
---|
6 | % |
---|
7 | % SETDIFF(A,B,'rows') when A are B are matrices with the same |
---|
8 | % number of columns returns the rows from A that are not in B. |
---|
9 | % |
---|
10 | % [C,I] = SETDIFF(...) also returns an index vector I such that |
---|
11 | % C = A(I) (or C = A(I,:)). |
---|
12 | % |
---|
13 | % See also UNIQUE, UNION, INTERSECT, SETXOR, ISMEMBER. |
---|
14 | |
---|
15 | % Copyright 1984-2003 The MathWorks, Inc. |
---|
16 | % $Revision: 1.5 $ $Date: 2005/02/09 22:08:06 $ |
---|
17 | |
---|
18 | % Cell array implementation in @cell/setdiff.m |
---|
19 | |
---|
20 | nIn = 2; |
---|
21 | isrows = 0; |
---|
22 | |
---|
23 | rowsA = size(a,1); |
---|
24 | colsA = size(a,2); |
---|
25 | rowsB = size(b,1); |
---|
26 | colsB = size(b,2); |
---|
27 | |
---|
28 | rowvec = ~((rowsA > 1 & colsB <= 1) | (rowsB > 1 & colsA <= 1) | isrows); |
---|
29 | |
---|
30 | nOut = 1; |
---|
31 | |
---|
32 | |
---|
33 | numelA = length(a); |
---|
34 | numelB = length(b); |
---|
35 | |
---|
36 | if prod(size(a))~=numelA | prod(size(b))~=numelB |
---|
37 | error('MATLAB:SETDIFF:AandBvectorsOrRowsFlag', ... |
---|
38 | 'A and B must be vectors or ''rows'' must be specified.'); |
---|
39 | end |
---|
40 | |
---|
41 | % Handle empty arrays. |
---|
42 | |
---|
43 | if (numelA == 0) |
---|
44 | % Predefine outputs to be of the correct type. |
---|
45 | c = a([]); |
---|
46 | ia = []; |
---|
47 | % Ambiguous if no way to determine whether to return a row or column. |
---|
48 | ambiguous = (rowsA==0 & colsA==0) & ... |
---|
49 | ((rowsB==0 & colsB==0) | numelB == 1); |
---|
50 | if ~ambiguous |
---|
51 | c = reshape(c,0,1); |
---|
52 | ia = reshape(ia,0,1); |
---|
53 | end |
---|
54 | elseif (numelB == 0) |
---|
55 | % If B is empty, invoke UNIQUE to remove duplicates from A. |
---|
56 | if nOut <= 1 |
---|
57 | c = unique(a); |
---|
58 | else |
---|
59 | [c,ia] = unique(a); |
---|
60 | end |
---|
61 | return |
---|
62 | |
---|
63 | % Handle scalar: one element. Scalar A done only. |
---|
64 | % Scalar B handled within ISMEMBER and general implementation. |
---|
65 | |
---|
66 | elseif (numelA == 1) |
---|
67 | if ~ismember(a,b) |
---|
68 | c = a; |
---|
69 | ia = 1; |
---|
70 | else |
---|
71 | c = []; |
---|
72 | ia = []; |
---|
73 | end |
---|
74 | return |
---|
75 | |
---|
76 | % General handling. |
---|
77 | |
---|
78 | else |
---|
79 | |
---|
80 | % Convert to columns. |
---|
81 | a = a(:); |
---|
82 | b = b(:); |
---|
83 | |
---|
84 | % Convert to double arrays, which sort faster than other types. |
---|
85 | |
---|
86 | whichclass = class(a); |
---|
87 | isdouble = strcmp(whichclass,'double'); |
---|
88 | |
---|
89 | if ~isdouble |
---|
90 | a = double(a); |
---|
91 | end |
---|
92 | |
---|
93 | if ~strcmp(class(b),'double') |
---|
94 | b = double(b); |
---|
95 | end |
---|
96 | |
---|
97 | % Call ISMEMBER to determine list of non-matching elements of A. |
---|
98 | tf = ~(ismember(a,b)); |
---|
99 | c = a(tf); |
---|
100 | |
---|
101 | % Call UNIQUE to remove duplicates from list of non-matches. |
---|
102 | if nargout <= 1 |
---|
103 | c = unique(c); |
---|
104 | else |
---|
105 | [c,ndx] = unique(c); |
---|
106 | |
---|
107 | % Find indices by using TF and NDX. |
---|
108 | where = find(tf); |
---|
109 | ia = where(ndx); |
---|
110 | end |
---|
111 | |
---|
112 | % Re-convert to correct output data type using FEVAL. |
---|
113 | if ~isdouble |
---|
114 | c = feval(whichclass,c); |
---|
115 | end |
---|
116 | end |
---|
117 | |
---|
118 | % If row vector, return as row vector. |
---|
119 | if rowvec |
---|
120 | c = c.'; |
---|
121 | if nOut > 1 |
---|
122 | ia = ia.'; |
---|
123 | end |
---|
124 | end |
---|
125 | |
---|
126 | |
---|
127 | % Automatically deblank strings |
---|
128 | if ischar(a) |
---|
129 | c = deblank(c); |
---|
130 | end |
---|