gusucode.com > datatypes 工具箱matlab源码程序 > datatypes/+matlab/+internal/+table/tableDimension.m
classdef (AllowedSubclasses = {?matlab.internal.table.tableRowNamesDim, ... ?matlab.internal.table.tableRowTimesDim, ... ?matlab.internal.table.tableVarNamesDim, ... ?matlab.internal.table.tableMetaDim}) tableDimension %TABLEDIMENSION Internal abstract class to represent a table's dimension. % This class is for internal use only and will change in a % future release. Do not use this class. % Copyright 2016 The MathWorks, Inc. properties(Abstract, Constant, GetAccess=public) propertyNames; end % *** these should be SetAccess=private, except that lengthenTo writes to them properties(GetAccess=public, SetAccess=protected) orientation length labels % Distinguish between not having labels and a zero-length dimension with no labels. hasLabels = false end % These are SetAccess=private and constant over the lifetime of the object properties(GetAccess=public, SetAccess=private) % A variables dimension must have labels, but a rows dimension needn't. requireLabels = true requireUniqueLabels = true end properties(Constant, GetAccess=public) subsType = struct('reference',0,'assignment',1,'deletion',2) end methods function obj = tableDimension(dimOrientation,dimLength,require,requireUnique,dimLabels) if nargin == 0 return end obj.orientation = dimOrientation; obj.length = dimLength; obj.requireLabels = require; obj.requireUniqueLabels = requireUnique; if nargin > 4 if isvector(dimLabels) && (length(dimLabels) == dimLength) obj.hasLabels = true; if dimOrientation == 1 obj.labels = dimLabels(:); % row labels as column else obj.labels = dimLabels(:)'; % var labels or meta labels as row end else obj.throwIncorrectNumberOfLabels(); end end end %----------------------------------------------------------------------- function obj = createLike(obj,dimLength,dimLabels) %CREATELIKE Create a tableDimension of the same kind as an existing one. if nargin < 3 obj = obj.createLike_impl(dimLength); else obj = obj.createLike_impl(dimLength,dimLabels); end end %----------------------------------------------------------------------- function obj = removeLabels(obj) if obj.requireLabels obj.throwRequiresLabels(); else obj.labels = {}; % optional labels is usually names obj.hasLabels = false; end end %----------------------------------------------------------------------- function labels = emptyLabels(obj,num) % EMPTYLABELS Return a vector of empty labels of the right kind. % Default behavior assumes the labels are names, subclasses with % non-name labels need to overload. if obj.orientation == 1 % row dim labels = repmat({''},num,1); else % var dim or meta dim labels = repmat({''},1,num); end end %----------------------------------------------------------------------- function labels = textLabels(obj,indices) % TEXTLABELS Return the labels converted to text. % Default behavior assumes the labels are names, subclasses with % non-name labels need to overload. if nargin < 2 labels = obj.labels; else labels = obj.labels(indices); end end %----------------------------------------------------------------------- function obj = selectFrom(obj,toSelect) %SELECTFROM Return a subset of a tableDimimension for the specified indices. % The indices might be out of order, that's OK or repeated, that's handled. obj = obj.selectFrom_impl(toSelect); end %----------------------------------------------------------------------- function obj = deleteFrom(obj,toDelete) %DELETEFROM Return a subset of a tableDimension with the specified indices removed. obj = obj.deleteFrom_impl(toDelete); end %----------------------------------------------------------------------- function obj = assignInto(obj,obj2,assignInto) obj = obj.assignInto_impl(obj2,assignInto); end %----------------------------------------------------------------------- function obj = moveProps(obj,obj2,from,to) %#ok<INUSD> % By default, the are no properties (other than labels). end %----------------------------------------------------------------------- function obj = mergeProps(obj,obj2,order) %#ok<INUSD> % By default, the are no properties (other than labels). end %----------------------------------------------------------------------- function obj = setLabels(obj,newLabels,subscripts,fixDups,fixEmpties,fixIllegal) %SETLABELS Modify, overwrite, or remove a tableDimProps's labels. if nargin < 6 % Should illegal labels be modified to make them legal? fixIllegal = false; if nargin < 5 % Should empty labels be filled in wth default labels? fixEmpties = false; if nargin < 4 % Should duplicate labels be made unique? fixDups = false; end end end % Subscripts equal to [] denotes a full assignment while the edge case of a % partial assignment to zero labels requires a 1x0 or 0x1 empty. fullAssignment = (nargin == 2) || isequal(subscripts,[]); if fullAssignment % replacing all labels indices = 1:obj.length; elseif obj.hasLabels % replacing some labels indices = obj.subs2inds(subscripts); else % don't allow a subscripted assignment to an empty property obj.throwInvalidPartialLabelsAssignment(); end % Check the type of the new labels, and convert them to the canonical type as % necessary (and allowed). If this is a full assignment of a 0x0, and removing % the labels is allowed, validateLabels leaves the shape alone, otherwise it % reshapes to a vector of the appropriate orientation. obj = obj.validateAndAssignLabels(newLabels,indices,fullAssignment,fixDups,fixEmpties,fixIllegal); end %----------------------------------------------------------------------- function [indices,numIndices,maxIndex,isColon,updatedObj] = subs2inds(obj,subscripts,subsType) if nargin < 3, subsType = obj.subsType.reference; end; % subsType default to reference (0) if nargout < 5 [indices,numIndices,maxIndex,isColon] = obj.subs2inds_impl(subscripts,subsType); else [indices,numIndices,maxIndex,isColon,updatedObj] = obj.subs2inds_impl(subscripts,subsType); end end end methods (Abstract) labels = defaultLabels(indices); obj = lengthenTo(obj,maxIndex,newLabels) s = getProperties(obj) end %=========================================================================== methods (Access=protected) function [indices,numIndices,maxIndex,isColon,updatedObj] = subs2inds_impl(obj,subscripts,subsType) %SUBS2INDS Convert table subscripts (labels, logical, numeric) to indices. % Translate a table subscript object into actual subscripts if isa(subscripts,'matlab.internal.datatypes.tableSubscript') subscripts = subscripts.getSubscripts(obj); end if isnumeric(subscripts) || islogical(subscripts) isColon = false; indices = subscripts(:); % Leave numeric and logical indices alone. if isnumeric(indices) if any(isnan(indices)) error(message('MATLAB:badsubscript',getString(message('MATLAB:badsubscriptTextRange')))); end numIndices = numel(indices); maxIndex = max(indices); else % logical numIndices = sum(indices); maxIndex = find(indices,1,'last'); end switch subsType case obj.subsType.reference if maxIndex > obj.length obj.throwIndexOutOfRange(); elseif nargout > 4 updatedObj = obj.selectFrom(indices); end case obj.subsType.assignment if nargout > 4 if maxIndex > obj.length updatedObj = obj.lengthenTo(maxIndex); else updatedObj = obj; end end case obj.subsType.deletion if maxIndex > obj.length obj.throwIndexOutOfRange(); elseif nargout > 4 updatedObj = obj.deleteFrom(indices); end otherwise assert(false); end elseif ischar(subscripts) && strcmp(subscripts, ':') % Leave ':' alone. isColon = true; indices = subscripts; numIndices = obj.length; maxIndex = obj.length; if nargout > 4 updatedObj = obj; end else % "native" subscripts, i.e. names or times isColon = false; % Translate labels into indices. [subscripts,indices] = obj.validateNativeSubscripts(subscripts); numIndices = numel(subscripts); maxIndex = max(indices(:)); switch subsType case obj.subsType.reference if nnz(indices) < numIndices if obj.requireUniqueLabels newLabels = unique(subscripts(~indices),'stable'); obj.throwUnrecognizedLabel(newLabels(1)); end indices = indices(indices>0); end if nargout > 4 updatedObj = obj.selectFrom(indices); end case obj.subsType.assignment if nnz(indices) < numIndices [newLabels,~,newIndices] = unique(subscripts(~indices),'stable'); indices(~indices) = obj.length + newIndices; maxIndex = max(indices(:)); if nargout > 4 updatedObj = obj.lengthenTo(maxIndex,newLabels); end elseif nargout > 4 updatedObj = obj; end case obj.subsType.deletion if nnz(indices) < numIndices newLabels = unique(subscripts(~indices),'stable'); obj.throwUnrecognizedLabel(newLabels(1)); elseif nargout > 4 updatedObj = obj.deleteFrom(indices); end otherwise assert(false); end end if obj.orientation == 1 indices = indices(:); else indices = indices(:)'; end end %----------------------------------------------------------------------- function obj = selectFrom_impl(obj,toSelect) %SELECTFROM_IMPL implements tableDimension's SELECTFROM method import matlab.internal.tableUtils.isUniqueNumeric if obj.hasLabels % Keep the labels the correct orientation. if obj.orientation == 1 obj.labels = obj.labels(toSelect(:)); else obj.labels = obj.labels(toSelect(:)'); end % Only numeric subscripts can lead to repeated rows (thus labels), no % need to check otherwise. if isnumeric(toSelect) && ~isUniqueNumeric(toSelect) obj = obj.makeUniqueForRepeatedIndices(toSelect); end obj.length = numel(obj.labels); elseif isnumeric(toSelect) obj.length = numel(toSelect); elseif islogical(toSelect) obj.length = sum(toSelect); elseif ischar(toSelect) && strcmp(toSelect, ':') % leave obj.length alone else assert(false); end end %----------------------------------------------------------------------- function obj = deleteFrom_impl(obj,toDelete) %DELETEFROM_IMPL implements tableDimension's DELETEFROM method if obj.hasLabels obj.labels(toDelete) = []; end keepIndices = 1:obj.length; keepIndices(toDelete) = []; obj.length = numel(keepIndices); end %----------------------------------------------------------------------- function obj = assignInto_impl(obj,obj2,assignInto) %ASSIGNINTO_IMPL implements tableDimension's ASSIGNITNO method if obj.hasLabels && obj2.hasLabels obj.labels(assignInto) = obj2.labels; elseif obj.hasLabels % && ~obj2.hasLabels obj.labels(assignInto) = obj2.emptyLabels(obj2.length); % *** creates invalid labels elseif obj2.hasLabels % && ~obj.hasLabels obj.labels = obj.emptyLabels(obj.length); obj.labels(assignInto) = obj2.labels; obj.hasLabels = true; end end %----------------------------------------------------------------------- function obj = createLike_impl(obj,dimLength,dimLabels) %CREATELIKE_IMPL implements tableDimension CREATELIKE method. obj.length = dimLength; if nargin < 3 if obj.hasLabels % This creates an invalid set of empty labels that must be set. obj.labels = obj.emptyLabels(dimLength); % *** creates invalid labels else obj.hasLabels = false; obj.labels = obj.labels([]); end else obj = obj.setLabels(dimLabels,[]); end end %----------------------------------------------------------------------- function obj = assignLabels(obj,newLabels,fullAssignment,indices) if fullAssignment if isvector(newLabels) % The number of new labels has to match what's being assigned to. if numel(newLabels) ~= obj.length obj.throwIncorrectNumberOfLabels(); end obj.hasLabels = true; obj.labels = newLabels; else % a 0x0 % Full assignment of a 0x0 clears out the existing labels, if allowed above by % the subclass's validateLabels. obj.labels = newLabels([]); % force a 0x0, for cosmetics obj.hasLabels = false; end else % subscripted assignment % The number of new labels has to match what's being assigned to. if numel(newLabels) ~= numel(indices) obj.throwIncorrectNumberOfLabelsPartial(); end obj.labels(indices) = newLabels; end end %----------------------------------------------------------------------- function [subscripts,indices] = validateNativeSubscripts(obj,subscripts) import matlab.internal.datatypes.isCharStrings % Default behavior assumes the labels are names, subclasses with % non-name labels need to overload. if ischar(subscripts) % already weeded out ':' if isrow(subscripts) subscripts = { subscripts }; else obj.throwInvalidLabel(); end elseif isCharStrings(subscripts) % require a cell array, don't allow empty character vectors in it % OK else obj.throwInvalidSubscripts(); end indices = zeros(size(subscripts)); labs = obj.labels; for i = 1:numel(indices) indFirstMatch = find(strcmp(subscripts{i},labs), 1); if indFirstMatch indices(i) = indFirstMatch; end end end end methods (Abstract, Access=protected) obj = validateAndAssignLabels(obj,newLabels,indices,fullAssignment,fixDups,fixEmpties,fixIllegal) obj = makeUniqueForRepeatedIndices(obj,indices) throwRequiresLabels(obj) throwInvalidPartialLabelsAssignment(obj) throwIncorrectNumberOfLabels(obj) throwIncorrectNumberOfLabelsPartial(obj) throwIndexOutOfRange(obj) throwUnrecognizedLabel(obj,label) throwInvalidLabel(obj) throwInvalidSubscripts(obj) end end