gusucode.com > datatypes 工具箱matlab源码程序 > datatypes/@tabular/setxor.m
function [c,ia,ib] = setxor(a,b,varargin) %SETXOR Find rows that occur in one or the other of two tables, but not both. % C = SETXOR(A,B) for tables A and B, returns the set of rows that are not in % the intersection of the two arrays, with repetitions removed. The rows in % the table C are sorted. % % A and B must have the same variable names, except for order. INTERSECT(A,B) % works on complete rows of A and B, considering all of their variables. To % find the exclusive or with respect to a subset of those variables, use % column subscripting such as SETXOR(A(:,VARS),B(:,VARS)), where VARS is a % positive integer, a vector of positive integers, a variable name, a cell % array of variable names, or a logical vector. % % SETXOR does not take row names of tables into account. Two rows that % have the same values but different names are considered equal. However, % when A and B are timetables, SETXOR does take the row times into % account in determining equal rows, and row times are used as the first % sorting variable. % % [C,IA,IB] = SETXOR(A,B) also returns index vectors IA and IB such that C is % a sorted combination of the values A(IA,:) and B(IB,:). If there are % repeated rows in A or B, then the index of the first occurrence is returned. % % [C,...] = SETXOR(A,B,'stable') returns the rows in C in the same order that % they appear in A, then B. % % [C,...] = SETXOR(A,B,'sorted') returns the rows in C in sorted order. This % is the default behavior. % % See also UNION, INTERSECT, SETDIFF, ISMEMBER, % UNIQUE, SORTROWS. % Copyright 2012-2016 The MathWorks, Inc. if ~isSameClass(a,b) error(message('MATLAB:table:setmembership:TypeMismatch')); end [tf,b2a] = ismember(b.varDim.labels,a.varDim.labels); if ~all(tf) || (length(tf) ~= a.varDim.length) error(message('MATLAB:table:setmembership:DisjointVars')); end avars = 1:a.varDim.length; bvars(1,b2a) = 1:b.varDim.length; if nargin < 3 flag = 'sorted'; else narginchk(2,5); % high=5, to let setmembershipFlagChecks sort flags out flag = setmembershipFlagChecks(varargin); end [ainds,binds] = table.table2midx(a,avars,b,bvars); % Calling setxor with either 'sorted' or 'stable' gives occurrence='first' [d,ia,ib] = setxorLocal(ainds,binds,flag,'rows'); aa = subsrefParens(a,substruct('()',{ia ':'})); bb = subsrefParens(b,substruct('()',{ib ':'})); if strcmp(flag,'sorted') ord(~d) = 1:length(ia); ord(d) = length(ia) + (1:length(ib)); iord(ord) = 1:length(ord); % vertcat would create unique default row names for aa or bb if necessary, but % after reordering for 'sorted', they'd have the wrong row number suffixes. % Create the right ones in advance. if aa.rowDim.hasLabels if ~bb.rowDim.hasLabels rowLabels = bb.rowDim.defaultLabels(iord(length(ia) + (1:length(ib)))); bb.rowDim = bb.rowDim.setLabels(rowLabels); end elseif bb.rowDim.hasLabels % && ~a.rowDim.hasLabels rowLabels = bb.rowDim.defaultLabels(iord(1:length(ia))); aa.rowDim = aa.rowDim.setLabels(rowLabels); end end c = [aa; bb]; % automatically merges the properties if strcmp(flag,'sorted') c = subsrefParens(c,substruct('()',{ord ':'})); end %----------------------------------------------------------------------- function [d,ia,ib] = setxorLocal(a,b,order,~) % The main function doesn't actually need the rows themselves, since those % are just dummy indices anyway. It needs to know which of the two inputs % each row of the xor "came from", so rather than returning the rows, this % local function returns a logical indicating rows of the result that came % from the second input (true), or from the first (false). % Make sure a and b contain unique elements. [uA,ia] = unique(a,'rows',order); [uB,ib] = unique(b,'rows',order); catuAuB = [uA;uB]; % Sort [uA;uB] in order to find matching entries [sortuAuB,indSortuAuB] = sortrows(catuAuB); d = find(all(sortuAuB(1:end-1,:)==sortuAuB(2:end,:),2)); % d indicates the location of matching entries indSortuAuB([d;d+1]) = []; % Remove all matching entries - indSortuAuB only contains elements not in intersect if strcmp(order, 'stable') % 'stable' indSortuAuB = sort(indSortuAuB); % Sort the indices to get 'stable' order end n = size(uA,1); d = indSortuAuB > n; ia = ia(indSortuAuB(~d,1),1); % Find indices in indSortuAuB that belong to A ib = ib(indSortuAuB(d,1)-n,1); % Find indices in indSortuAuB that belong to B