1function A = catstruct(varargin) 2% CATSTRUCT Concatenate or merge structures with different fieldnames 3% X = CATSTRUCT(S1,S2,S3,...) merges the structures S1, S2, S3 ... 4% into one new structure X. X contains all fields present in the various 5% structures. An example: 6% 7% A.name = 'Me' ; 8% B.income = 99999 ; 9% X = catstruct(A,B) 10% % -> X.name = 'Me' ; 11% % X.income = 99999 ; 12% 13% If a fieldname is not unique among structures (i.e., a fieldname is 14% present in more than one structure), only the value from the last 15% structure with this field is used. In this case, the fields are 16% alphabetically sorted. A warning is issued as well. An axample: 17% 18% S1.name = 'Me' ; 19% S2.age = 20 ; S3.age = 30 ; S4.age = 40 ; 20% S5.honest = false ; 21% Y = catstruct(S1,S2,S3,S4,S5) % use value from S4 22% 23% The inputs can be array of structures. All structures should have the 24% same size. An example: 25% 26% C(1).bb = 1 ; C(2).bb = 2 ; 27% D(1).aa = 3 ; D(2).aa = 4 ; 28% CD = catstruct(C,D) % CD is a 1x2 structure array with fields bb and aa 29% 30% The last input can be the string 'sorted'. In this case, 31% CATSTRUCT(S1,S2, ..., 'sorted') will sort the fieldnames alphabetically. 32% To sort the fieldnames of a structure A, you could use 33% CATSTRUCT(A,'sorted') but I recommend ORDERFIELDS for doing that. 34% 35% When there is nothing to concatenate, the result will be an empty 36% struct (0x0 struct array with no fields). 37% 38% NOTE: To concatenate similar arrays of structs, you can use simple 39% concatenation: 40% A = dir('*.mat') ; B = dir('*.m') ; C = [A ; B] ; 41% 42% See also CAT, STRUCT, FIELDNAMES, STRUCT2CELL, ORDERFIELDS 43 44% for Matlab R13 and up 45% version 3.0 (mar 2013) 46% Originally downloaded from MATLAB central: 47% http://www.mathworks.com/matlabcentral/fileexchange/7842-catstruct 48 49% Copyright (C) 2005 Jos van der Geest <jos@jasen.nl> 50% Copyright (C) 2013 Christophe Gouel 51% Copyright (C) 2016-2020 Dynare Team 52% 53% Redistribution and use in source and binary forms, with or without 54% modification, are permitted provided that the following conditions are 55% met: 56% 57% * Redistributions of source code must retain the above copyright 58% notice, this list of conditions and the following disclaimer. 59% * Redistributions in binary form must reproduce the above copyright 60% notice, this list of conditions and the following disclaimer in 61% the documentation and/or other materials provided with the distribution 62% 63% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 64% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 65% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 66% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 67% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 68% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 69% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 70% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 71% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 72% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 73% POSSIBILITY OF SUCH DAMAGE. 74 75% History 76% Created in 2005 77% Revisions 78% 2.0 (sep 2007) removed bug when dealing with fields containing cell 79% arrays (Thanks to Rene Willemink) 80% 2.1 (sep 2008) added warning and error identifiers 81% 2.2 (oct 2008) fixed error when dealing with empty structs (Thanks to 82% Lars Barring) 83% 3.0 (mar 2013) fixed problem when the inputs were array of structures 84% (thanks to Tor Inge Birkenes for pointing this out). 85% Rephrased the help section as well. 86 87narginchk(1, Inf); 88N = nargin ; 89 90if ~isstruct(varargin{end}) 91 if isequal(varargin{end},'sorted') 92 sorted = 1 ; 93 N = N-1 ; 94 if N<1 95 error('catstruct: wrong number of input arguments') ; 96 end 97 else 98 error('catstruct:InvalidArgument','Last argument should be a structure, or the string "sorted".') ; 99 end 100else 101 sorted = 0 ; 102end 103 104sz0 = [] ; % used to check that all inputs have the same size 105 106% used to check for a few trivial cases 107NonEmptyInputs = false(N,1) ; 108NonEmptyInputsN = 0 ; 109 110% used to collect the fieldnames and the inputs 111FN = cell(N,1) ; 112VAL = cell(N,1) ; 113 114% parse the inputs 115for ii=1:N 116 X = varargin{ii} ; 117 if ~isstruct(X) 118 error('catstruct:InvalidArgument',['Argument #' num2str(ii) ' is not a structure.']) ; 119 end 120 121 if ~isempty(X) 122 % empty structs are ignored 123 if ii > 1 && ~isempty(sz0) 124 if ~isequal(size(X), sz0) 125 error('catstruct:UnequalSizes','All structures should have the same size.') ; 126 end 127 else 128 sz0 = size(X) ; 129 end 130 NonEmptyInputsN = NonEmptyInputsN + 1 ; 131 NonEmptyInputs(ii) = true ; 132 FN{ii} = fieldnames(X) ; 133 VAL{ii} = struct2cell(X) ; 134 end 135end 136 137if NonEmptyInputsN == 0 138 % all structures were empty 139 A = struct([]) ; 140elseif NonEmptyInputsN == 1 141 % there was only one non-empty structure 142 A = varargin{NonEmptyInputs} ; 143 if sorted 144 A = orderfields(A) ; 145 end 146else 147 % there is actually something to concatenate 148 FN = cat(1,FN{:}) ; 149 VAL = cat(1,VAL{:}) ; 150 FN = squeeze(FN) ; 151 VAL = squeeze(VAL) ; 152 MatlabVersion = version; 153 if (isoctave && octave_ver_less_than('6')) || (~isoctave && str2double(MatlabVersion(end-5:end-2))<2013) % Equivalent to, but faster than if verLessThan('matlab','8.1') 154 [UFN,ind] = unique(FN) ; 155 else 156 [UFN,ind] = unique(FN,'legacy') ; 157 end 158 159 if numel(UFN) ~= numel(FN) 160 warning('catstruct:DuplicatesFound','Fieldnames are not unique between structures.') ; 161 sorted = 1 ; 162 end 163 164 if sorted 165 VAL = VAL(ind,:) ; 166 FN = FN(ind,:) ; 167 end 168 169 A = cell2struct(VAL, FN); 170 A = reshape(A, sz0) ; % reshape into original format 171end 172