comparison scripts/set/setdiff.m @ 19003:d00f6b09258f @

Overhaul functions in scripts/set directory. * set.txi: Rewrite documentation for set functions. * intersect.m: Rewrite docstring. Use by_rows variable for code clarity. Return output orientation which is compatible with Matlab. Add %!tests for output orientation and N-dimensional inputs. * setdiff.m: Rewrite docstring. Use by_rows variable for code clarity. Rename output i to ia to clarify it is an index into the set a. Return output orientation which is compatible with Matlab. Add %!tests for N-dimensional inputs. * setxor.m: Rewrite docstring. Use by_rows variable for code clarity. Return output orientation which is compatible with Matlab. Add %!tests for output orientation and N-dimensional inputs. * union.m: Rewrite docstring. Use by_rows variable for code clarity. Return output orientation which is compatible with Matlab. Add %!tests for output orientation and N-dimensional inputs. Add %!tests for validsetargs which are common to all set functions. * unique.m: Rewrite docstring. Verify that input is numeric or cell array of strings. Avoid computing idx for optional i,j outputs unless required. Add %!error tests for input validation. * ismember.m: Rewrite docstring. Use input variable 'a' instead of 'A' for conformance with rest of set functions. Rename output index variable to s_idx for clarity that it is an index into the set s. * powerset.m: Rewrite doctring. Add input validation on nargin. Add %!error input validation tests. * module.mk: Include validsetargs.m in build system. * validsetargs.m: Function renamed from validargs which was too general. * validargs.m: Function renamed to validsetargs.
author Rik <rik@octave.org>
date Mon, 11 Aug 2014 09:39:45 -0700
parents 30d8501a857a
children
comparison
equal deleted inserted replaced
19001:391e080ae810 19003:d00f6b09258f
16 ## You should have received a copy of the GNU General Public License 16 ## You should have received a copy of the GNU General Public License
17 ## along with Octave; see the file COPYING. If not, see 17 ## along with Octave; see the file COPYING. If not, see
18 ## <http://www.gnu.org/licenses/>. 18 ## <http://www.gnu.org/licenses/>.
19 19
20 ## -*- texinfo -*- 20 ## -*- texinfo -*-
21 ## @deftypefn {Function File} {} setdiff (@var{a}, @var{b}) 21 ## @deftypefn {Function File} {@var{c} =} setdiff (@var{a}, @var{b})
22 ## @deftypefnx {Function File} {} setdiff (@var{a}, @var{b}, "rows") 22 ## @deftypefnx {Function File} {@var{c} =} setdiff (@var{a}, @var{b}, "rows")
23 ## @deftypefnx {Function File} {[@var{c}, @var{i}] =} setdiff (@var{a}, @var{b}) 23 ## @deftypefnx {Function File} {[@var{c}, @var{ia}] =} setdiff (@dots{})
24 ## Return the elements in @var{a} that are not in @var{b}, sorted in 24 ## Return the elements in @var{a} that are not in @var{b} sorted in
25 ## ascending order. If @var{a} and @var{b} are both column vectors 25 ## ascending order.
26 ## return a column vector, otherwise return a row vector.
27 ## @var{a}, @var{b} may be cell arrays of string(s).
28 ## 26 ##
29 ## Given the optional third argument @qcode{"rows"}, return the rows in 27 ## If @var{a} and @var{b} are both column vectors return a column vector;
30 ## @var{a} that are not in @var{b}, sorted in ascending order by rows. 28 ## Otherwise, return a row vector. The inputs may also be cell arrays of
29 ## strings.
31 ## 30 ##
32 ## If requested, return @var{i} such that @code{c = a(i)}. 31 ## If the optional input @qcode{"rows"} is given then return the rows in
32 ## @var{a} that are not in @var{b}. The inputs must be 2-D matrices to use
33 ## this option.
34 ##
35 ## If requested, return the index vector @var{ia} such that
36 ## @code{@var{c} = @var{a}(@var{ia})}.
33 ## @seealso{unique, union, intersect, setxor, ismember} 37 ## @seealso{unique, union, intersect, setxor, ismember}
34 ## @end deftypefn 38 ## @end deftypefn
35 39
36 ## Author: Paul Kienzle 40 ## Author: Paul Kienzle
37 ## Adapted-by: jwe 41 ## Adapted-by: jwe
38 42
39 function [c, i] = setdiff (a, b, varargin) 43 function [c, ia] = setdiff (a, b, varargin)
40 44
41 if (nargin < 2 || nargin > 3) 45 if (nargin < 2 || nargin > 3)
42 print_usage (); 46 print_usage ();
43 endif 47 endif
44 48
45 [a, b] = validargs ("setdiff", a, b, varargin{:}); 49 [a, b] = validsetargs ("setdiff", a, b, varargin{:});
46 50
47 if (nargin > 2) 51 by_rows = nargin == 3;
52 iscol = isvector (a) && isvector (b) && iscolumn (a) && iscolumn (b);
53
54 if (by_rows)
48 if (nargout > 1) 55 if (nargout > 1)
49 [c, i] = unique (a, "rows"); 56 [c, ia] = unique (a, "rows");
50 else 57 else
51 c = unique (a, "rows"); 58 c = unique (a, "rows");
52 endif 59 endif
53 if (! isempty (c) && ! isempty (b)) 60 if (! isempty (c) && ! isempty (b))
54 ## Form a and b into combined set. 61 ## Form A and B into combined set.
55 b = unique (b, "rows"); 62 b = unique (b, "rows");
56 [dummy, idx] = sortrows ([c; b]); 63 [tmp, idx] = sortrows ([c; b]);
57 ## Eliminate those elements of a that are the same as in b. 64 ## Eliminate those elements of A that are the same as in B.
58 dups = find (all (dummy(1:end-1,:) == dummy(2:end,:), 2)); 65 dups = find (all (tmp(1:end-1,:) == tmp(2:end,:), 2));
59 c(idx(dups),:) = []; 66 c(idx(dups),:) = [];
60 if (nargout > 1) 67 if (nargout > 1)
61 i(idx(dups),:) = []; 68 ia(idx(dups),:) = [];
62 endif 69 endif
63 endif 70 endif
64 else 71 else
65 if (nargout > 1) 72 if (nargout > 1)
66 [c, i] = unique (a); 73 [c, ia] = unique (a);
67 else 74 else
68 c = unique (a); 75 c = unique (a);
69 endif 76 endif
70 if (! isempty (c) && ! isempty (b)) 77 if (! isempty (c) && ! isempty (b))
71 ## Form a and b into combined set. 78 ## Form a and b into combined set.
72 b = unique (b); 79 b = unique (b);
73 [dummy, idx] = sort ([c(:); b(:)]); 80 [tmp, idx] = sort ([c(:); b(:)]);
74 ## Eliminate those elements of a that are the same as in b. 81 ## Eliminate those elements of a that are the same as in b.
75 if (iscellstr (dummy)) 82 if (iscellstr (tmp))
76 dups = find (strcmp (dummy(1:end-1), dummy(2:end))); 83 dups = find (strcmp (tmp(1:end-1), tmp(2:end)));
77 else 84 else
78 dups = find (dummy(1:end-1) == dummy(2:end)); 85 dups = find (tmp(1:end-1) == tmp(2:end));
79 endif 86 endif
80 c(idx(dups)) = []; 87 c(idx(dups)) = [];
81 if (nargout > 1) 88 if (nargout > 1)
82 i(idx(dups)) = []; 89 ia(idx(dups)) = [];
83 endif 90 endif
84 ## Reshape if necessary for Matlab compatibility. 91 ## Reshape if necessary for Matlab compatibility.
85 if (iscolumn (c) && ! iscolumn (b)) 92 if (iscol)
86 c = c.'; 93 c = c(:);
94 else
95 c = c(:).';
87 endif 96 endif
88 endif 97 endif
89 endif 98 endif
90 99
91 endfunction 100 endfunction
98 %!assert (setdiff ([1; 2; 3; 4], [1; 2; 4], "rows"), 3) 107 %!assert (setdiff ([1; 2; 3; 4], [1; 2; 4], "rows"), 3)
99 %!assert (setdiff ([1, 2; 3, 4], [1, 2; 3, 6], "rows"), [3, 4]) 108 %!assert (setdiff ([1, 2; 3, 4], [1, 2; 3, 6], "rows"), [3, 4])
100 %!assert (setdiff ({"one","two";"three","four"}, {"one","two";"three","six"}), {"four"}) 109 %!assert (setdiff ({"one","two";"three","four"}, {"one","two";"three","six"}), {"four"})
101 110
102 %!test 111 %!test
103 %! a = [3, 1, 4, 1, 5]; b = [1, 2, 3, 4]; 112 %! a = [3, 1, 4, 1, 5];
104 %! [y, i] = setdiff (a, b.'); 113 %! b = [1, 2, 3, 4];
105 %! assert (y, [5]); 114 %! [c, ia] = setdiff (a, b');
106 %! assert (y, a(i)); 115 %! assert (c, [5]);
116 %! assert (c, a(ia));
107 117
108 %% Test output orientation compatibility (bug #42577) 118 %% Test output orientation compatibility (bug #42577)
109 %!assert (setdiff ([1:5], 2), [1,3,4,5]) 119 %!assert (setdiff ([1:5], 2), [1,3,4,5])
110 %!assert (setdiff ([1:5]', 2), [1;3;4;5]) 120 %!assert (setdiff ([1:5]', 2), [1;3;4;5])
111 %!assert (setdiff ([1:5], [2:3]), [1,4,5]) 121 %!assert (setdiff ([1:5], [2:3]), [1,4,5])
112 %!assert (setdiff ([1:5], [2:3]'), [1,4,5]) 122 %!assert (setdiff ([1:5], [2:3]'), [1,4,5])
113 %!assert (setdiff ([1:5]', [2:3]), [1,4,5]) 123 %!assert (setdiff ([1:5]', [2:3]), [1,4,5])
114 %!assert (setdiff ([1:5]', [2:3]'), [1;4;5]) 124 %!assert (setdiff ([1:5]', [2:3]'), [1;4;5])
115 125
116 %% Test input validation 126 %!test
117 %!error setdiff () 127 %! a = rand (3,3,3);
118 %!error setdiff (1) 128 %! b = a(1);
119 %!error setdiff (1,2,3,4) 129 %! assert (setdiff (a, b), sort (a(2:end)));
120 130