Home > utilities > catstruct.m

catstruct

PURPOSE ^

CATSTRUCT Concatenate or merge structures with different fieldnames

SYNOPSIS ^

function A = catstruct(varargin)

DESCRIPTION ^

 CATSTRUCT   Concatenate or merge structures with different fieldnames
   X = CATSTRUCT(S1,S2,S3,...) merges the structures S1, S2, S3 ...
   into one new structure X. X contains all fields present in the various
   structures. An example:

     A.name = 'Me' ;
     B.income = 99999 ;
     X = catstruct(A,B) 
     % -> X.name = 'Me' ;
     %    X.income = 99999 ;

   If a fieldname is not unique among structures (i.e., a fieldname is
   present in more than one structure), only the value from the last
   structure with this field is used. In this case, the fields are 
   alphabetically sorted. A warning is issued as well. An axample:

     S1.name = 'Me' ;
     S2.age  = 20 ; S3.age  = 30 ; S4.age  = 40 ;
     S5.honest = false ;
     Y = catstruct(S1,S2,S3,S4,S5) % use value from S4

   The inputs can be array of structures. All structures should have the
   same size. An example:

     C(1).bb = 1 ; C(2).bb = 2 ;
     D(1).aa = 3 ; D(2).aa = 4 ;
     CD = catstruct(C,D) % CD is a 1x2 structure array with fields bb and aa

   The last input can be the string 'sorted'. In this case,
   CATSTRUCT(S1,S2, ..., 'sorted') will sort the fieldnames alphabetically. 
   To sort the fieldnames of a structure A, you could use
   CATSTRUCT(A,'sorted') but I recommend ORDERFIELDS for doing that.

   When there is nothing to concatenate, the result will be an empty
   struct (0x0 struct array with no fields).

   NOTE: To concatenate similar arrays of structs, you can use simple
   concatenation: 
     A = dir('*.mat') ; B = dir('*.m') ; C = [A ; B] ;

   See also CAT, STRUCT, FIELDNAMES, STRUCT2CELL, ORDERFIELDS

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SOURCE CODE ^

0001 function A = catstruct(varargin)
0002 % CATSTRUCT   Concatenate or merge structures with different fieldnames
0003 %   X = CATSTRUCT(S1,S2,S3,...) merges the structures S1, S2, S3 ...
0004 %   into one new structure X. X contains all fields present in the various
0005 %   structures. An example:
0006 %
0007 %     A.name = 'Me' ;
0008 %     B.income = 99999 ;
0009 %     X = catstruct(A,B)
0010 %     % -> X.name = 'Me' ;
0011 %     %    X.income = 99999 ;
0012 %
0013 %   If a fieldname is not unique among structures (i.e., a fieldname is
0014 %   present in more than one structure), only the value from the last
0015 %   structure with this field is used. In this case, the fields are
0016 %   alphabetically sorted. A warning is issued as well. An axample:
0017 %
0018 %     S1.name = 'Me' ;
0019 %     S2.age  = 20 ; S3.age  = 30 ; S4.age  = 40 ;
0020 %     S5.honest = false ;
0021 %     Y = catstruct(S1,S2,S3,S4,S5) % use value from S4
0022 %
0023 %   The inputs can be array of structures. All structures should have the
0024 %   same size. An example:
0025 %
0026 %     C(1).bb = 1 ; C(2).bb = 2 ;
0027 %     D(1).aa = 3 ; D(2).aa = 4 ;
0028 %     CD = catstruct(C,D) % CD is a 1x2 structure array with fields bb and aa
0029 %
0030 %   The last input can be the string 'sorted'. In this case,
0031 %   CATSTRUCT(S1,S2, ..., 'sorted') will sort the fieldnames alphabetically.
0032 %   To sort the fieldnames of a structure A, you could use
0033 %   CATSTRUCT(A,'sorted') but I recommend ORDERFIELDS for doing that.
0034 %
0035 %   When there is nothing to concatenate, the result will be an empty
0036 %   struct (0x0 struct array with no fields).
0037 %
0038 %   NOTE: To concatenate similar arrays of structs, you can use simple
0039 %   concatenation:
0040 %     A = dir('*.mat') ; B = dir('*.m') ; C = [A ; B] ;
0041 %
0042 %   See also CAT, STRUCT, FIELDNAMES, STRUCT2CELL, ORDERFIELDS
0043 
0044 % for Matlab R13 and up
0045 % version 3.0 (mar 2013)
0046 % (c) Jos van der Geest
0047 % email: jos@jasen.nl
0048 
0049 % History
0050 % Created in 2005
0051 % Revisions
0052 %   2.0 (sep 2007) removed bug when dealing with fields containing cell
0053 %                  arrays (Thanks to Rene Willemink)
0054 %   2.1 (sep 2008) added warning and error identifiers
0055 %   2.2 (oct 2008) fixed error when dealing with empty structs (Thanks to
0056 %                  Lars Barring)
0057 %   3.0 (mar 2013) fixed problem when the inputs were array of structures
0058 %                  (thanks to Tor Inge Birkenes for pointing this out).
0059 %                  Rephrased the help section as well.
0060 
0061 error(nargchk(1,Inf,nargin)) ;
0062 N = nargin ;
0063 
0064 if ~isstruct(varargin{end}),
0065     if isequal(varargin{end},'sorted'),
0066         sorted = 1 ;
0067         N = N-1 ;
0068         error(nargchk(1,Inf,N)) ;
0069     else
0070         error('catstruct:InvalidArgument','Last argument should be a structure, or the string "sorted".') ;
0071     end
0072 else
0073     sorted = 0 ;
0074 end
0075 
0076 sz0 = [] ; % used to check that all inputs have the same size
0077 
0078 % used to check for a few trivial cases
0079 NonEmptyInputs = false(N,1) ; 
0080 NonEmptyInputsN = 0 ;
0081 
0082 % used to collect the fieldnames and the inputs
0083 FN = cell(N,1) ;
0084 VAL = cell(N,1) ;
0085 
0086 % parse the inputs
0087 for ii=1:N,
0088     X = varargin{ii} ;
0089     if ~isstruct(X),
0090         error('catstruct:InvalidArgument',['Argument #' num2str(ii) ' is not a structure.']) ;
0091     end
0092     
0093     if ~isempty(X),
0094         % empty structs are ignored
0095         if ii > 1 && ~isempty(sz0)
0096             if ~isequal(size(X), sz0)
0097                 error('catstruct:UnequalSizes','All structures should have the same size.') ;
0098             end
0099         else
0100             sz0 = size(X) ;
0101         end
0102         NonEmptyInputsN = NonEmptyInputsN + 1 ;
0103         NonEmptyInputs(ii) = true ;
0104         FN{ii} = fieldnames(X) ;
0105         VAL{ii} = struct2cell(X) ;
0106     end
0107 end
0108 
0109 if NonEmptyInputsN == 0
0110     % all structures were empty
0111     A = struct([]) ;
0112 elseif NonEmptyInputsN == 1,
0113     % there was only one non-empty structure
0114     A = varargin{NonEmptyInputs} ;
0115     if sorted,
0116         A = orderfields(A) ;
0117     end
0118 else
0119     % there is actually something to concatenate
0120     FN = cat(1,FN{:}) ;    
0121     VAL = cat(1,VAL{:}) ;    
0122     FN = squeeze(FN) ;
0123     VAL = squeeze(VAL) ;
0124     [UFN,ind] = unique(FN) ;
0125     
0126     if numel(UFN) ~= numel(FN),
0127         warning('catstruct:DuplicatesFound','Fieldnames are not unique between structures.') ;
0128         sorted = 1 ;
0129     end
0130     
0131     if sorted,
0132         VAL = VAL(ind,:) ;
0133         FN = FN(ind,:) ;
0134     end
0135     
0136     A = cell2struct(VAL, FN);
0137     A = reshape(A, sz0) ; % reshape into original format
0138 end
0139 
0140 
0141

Generated on Wed 20-Feb-2019 16:06:01 by m2html © 2005