gusucode.com > bigdata 工具箱 matlab源码程序 > bigdata/+matlab/+bigdata/+internal/+adaptors/combineAdaptors.m
function out = combineAdaptors(dim, inCell) %combineAdaptors Combination of adaptors for horizontal concatenation % Copyright 2016 The MathWorks, Inc. adaptorClasses = cellfun(@class, inCell, 'UniformOutput', false); underlyingClasses = cellfun(@(x) x.Class, inCell, 'UniformOutput', false); isKnownUniqueUnderlyingClass = numel(unique(underlyingClasses)) == 1 && ... ~isempty(underlyingClasses{1}); % Allowed combinations: % - all 'generic' adaptors, return a plain generic adaptor % - all DatetimeFamilyAdaptor % - if classes all match % - or duration + calendarDuration -> calendarDuration % - datetime and char/string -> datetime % - duration|calendarDuration and numeric -> duration|calendarDuration % - all TableAdaptor - concatenate VariableNames and Adaptors providing VariableNames unique % - categorical will need special handling when it becomes a "strong" type. % - if 'string' were to become a "strong" type, more special handling needed. if all(strcmp(adaptorClasses, 'matlab.bigdata.internal.adaptors.GenericAdaptor')) out = matlab.bigdata.internal.adaptors.GenericAdaptor(); if isKnownUniqueUnderlyingClass out = matlab.bigdata.internal.adaptors.getAdaptorForType(underlyingClasses{1}); end elseif any(strcmp(adaptorClasses, 'matlab.bigdata.internal.adaptors.DatetimeFamilyAdaptor')) % Here we still consider unknown (empty) classes uc = unique(underlyingClasses); if numel(uc) == 1 out = matlab.bigdata.internal.adaptors.DatetimeFamilyAdaptor(underlyingClasses{1}); else % We need to work out from the known-good combinations of classes. Disregard % unknown classes for now, treat them as if they'll work, and hope for % the best. uc(isempty(uc)) = []; if isempty(setdiff(uc, { 'datetime', 'char', 'string', 'cell' })) outClass = 'datetime'; elseif isempty(setdiff(uc, { 'duration', 'double', 'logical' })) outClass = 'duration'; elseif isempty(setdiff(uc, { 'duration', 'calendarDuration', 'double', 'logical' })) outClass = 'calendarDuration'; else error(message('MATLAB:bigdata:array:InvalidConcatenation', strjoin(uc, ' '))); end out = matlab.bigdata.internal.adaptors.DatetimeFamilyAdaptor(outClass); end elseif all(strcmp(adaptorClasses, 'matlab.bigdata.internal.adaptors.TableAdaptor')) allVarNames = cellfun(@(x) x.VariableNames, inCell, 'UniformOutput', false); allVarNames = [allVarNames{:}]; [uniqueVarNames, ~, ic] = unique(allVarNames); if numel(allVarNames) ~= numel(uniqueVarNames) % find first duplicate, and error as per table/cat ... occurenceCount = accumarray(ic, 1); firstNonUnique = find(occurenceCount > 1, 1, 'first'); assert(isscalar(firstNonUnique)); firstNonUniqueName = uniqueVarNames{firstNonUnique}; error(message('MATLAB:table:DuplicateVarNames', firstNonUniqueName)); else newVarNames = reshape(allVarNames, 1, []); allAdaptors = cellfun(@(x) x.VariableAdaptors, inCell, 'UniformOutput', false); newAdaptors = [allAdaptors{:}]; out = matlab.bigdata.internal.adaptors.TableAdaptor(newVarNames, newAdaptors); end elseif any(strcmp(adaptorClasses, 'matlab.bigdata.internal.adaptors.CategoricalAdaptor')) % categorical can combine with: string, char, cell(str) - result is always categorical. uc = unique(underlyingClasses); % Remove unknown classes (which might error later) uc(isempty(uc)) = []; % Remove known-good classes, leaving only forbidden classes forbiddenClasses = setdiff(uc, { 'categorical', 'string', 'char', 'cell' }); if isempty(forbiddenClasses) out = matlab.bigdata.internal.adaptors.CategoricalAdaptor(); else error(message('MATLAB:bigdata:array:InvalidConcatenation', strjoin(uc, ' '))); end else % Throw a vague error about not being able to concatenate error(message('MATLAB:bigdata:array:InvalidConcatenationUnknownTypes')); end % Attempt to propagate known size information by concatenating the sizes, but % only if all small dimensions are known, and all classes are known and match % (see g1393370 for what can happen when classes don't match - sizes can % change!) allNdims = cellfun(@(a) a.NDims, inCell); if isscalar(inCell) out = copySizeInformation(out, inCell{1}); elseif ~any(isnan(allNdims)) && isKnownUniqueUnderlyingClass effectiveNdims = max(dim, max(allNdims)); % Function to get the size from the adaptor in a vector of length % effectiveNdims. szAsCellFcn = @(a) { [a.Size, ones(1, max(0, effectiveNdims - a.NDims))] }; % Get a matrix of all sizes allSizes = cell2mat(cellfun(szAsCellFcn, reshape(inCell, [], 1))); % Work out the dimensions for which we know the sizes knownSizeDims = all(~isnan(allSizes), 1); % We need matches in dimensions that are known and not the concatenation % dimension. checkDims = knownSizeDims; checkDims(dim) = false; % Do the sizes match? sizesToCheck = allSizes(:, checkDims); doMatch = size(unique(sizesToCheck, 'rows'), 1) == 1; if doMatch newSize = allSizes(1, :); newSize(dim) = sum(allSizes(:, dim)); out = setKnownSize(out, newSize); else error(message('MATLAB:bigdata:array:CatDimensionMismatch')); end end