172 lines
5.9 KiB
Matlab
172 lines
5.9 KiB
Matlab
function A = catstruct(varargin)
|
|
% 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
|
|
|
|
% for Matlab R13 and up
|
|
% version 3.0 (mar 2013)
|
|
% Originally downloaded from MATLAB central:
|
|
% http://www.mathworks.com/matlabcentral/fileexchange/7842-catstruct
|
|
|
|
% Copyright (C) 2005 Jos van der Geest <jos@jasen.nl>
|
|
% Copyright (C) 2013 Christophe Gouel
|
|
% Copyright (C) 2016-2017 Dynare Team
|
|
%
|
|
% Redistribution and use in source and binary forms, with or without
|
|
% modification, are permitted provided that the following conditions are
|
|
% met:
|
|
%
|
|
% * Redistributions of source code must retain the above copyright
|
|
% notice, this list of conditions and the following disclaimer.
|
|
% * Redistributions in binary form must reproduce the above copyright
|
|
% notice, this list of conditions and the following disclaimer in
|
|
% the documentation and/or other materials provided with the distribution
|
|
%
|
|
% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
% POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
% History
|
|
% Created in 2005
|
|
% Revisions
|
|
% 2.0 (sep 2007) removed bug when dealing with fields containing cell
|
|
% arrays (Thanks to Rene Willemink)
|
|
% 2.1 (sep 2008) added warning and error identifiers
|
|
% 2.2 (oct 2008) fixed error when dealing with empty structs (Thanks to
|
|
% Lars Barring)
|
|
% 3.0 (mar 2013) fixed problem when the inputs were array of structures
|
|
% (thanks to Tor Inge Birkenes for pointing this out).
|
|
% Rephrased the help section as well.
|
|
|
|
narginchk(1, Inf);
|
|
N = nargin ;
|
|
|
|
if ~isstruct(varargin{end})
|
|
if isequal(varargin{end},'sorted')
|
|
sorted = 1 ;
|
|
N = N-1 ;
|
|
if N<1
|
|
error('catstruct: wrong number of input arguments') ;
|
|
end
|
|
else
|
|
error('catstruct:InvalidArgument','Last argument should be a structure, or the string "sorted".') ;
|
|
end
|
|
else
|
|
sorted = 0 ;
|
|
end
|
|
|
|
sz0 = [] ; % used to check that all inputs have the same size
|
|
|
|
% used to check for a few trivial cases
|
|
NonEmptyInputs = false(N,1) ;
|
|
NonEmptyInputsN = 0 ;
|
|
|
|
% used to collect the fieldnames and the inputs
|
|
FN = cell(N,1) ;
|
|
VAL = cell(N,1) ;
|
|
|
|
% parse the inputs
|
|
for ii=1:N
|
|
X = varargin{ii} ;
|
|
if ~isstruct(X)
|
|
error('catstruct:InvalidArgument',['Argument #' num2str(ii) ' is not a structure.']) ;
|
|
end
|
|
|
|
if ~isempty(X)
|
|
% empty structs are ignored
|
|
if ii > 1 && ~isempty(sz0)
|
|
if ~isequal(size(X), sz0)
|
|
error('catstruct:UnequalSizes','All structures should have the same size.') ;
|
|
end
|
|
else
|
|
sz0 = size(X) ;
|
|
end
|
|
NonEmptyInputsN = NonEmptyInputsN + 1 ;
|
|
NonEmptyInputs(ii) = true ;
|
|
FN{ii} = fieldnames(X) ;
|
|
VAL{ii} = struct2cell(X) ;
|
|
end
|
|
end
|
|
|
|
if NonEmptyInputsN == 0
|
|
% all structures were empty
|
|
A = struct([]) ;
|
|
elseif NonEmptyInputsN == 1
|
|
% there was only one non-empty structure
|
|
A = varargin{NonEmptyInputs} ;
|
|
if sorted
|
|
A = orderfields(A) ;
|
|
end
|
|
else
|
|
% there is actually something to concatenate
|
|
FN = cat(1,FN{:}) ;
|
|
VAL = cat(1,VAL{:}) ;
|
|
FN = squeeze(FN) ;
|
|
VAL = squeeze(VAL) ;
|
|
MatlabVersion = version;
|
|
if isoctave || str2double(MatlabVersion(end-5:end-2))<2013 % Equivalent to, but faster than if verLessThan('matlab','8.1')
|
|
[UFN,ind] = unique(FN) ;
|
|
else
|
|
[UFN,ind] = unique(FN,'legacy') ;
|
|
end
|
|
|
|
if numel(UFN) ~= numel(FN)
|
|
warning('catstruct:DuplicatesFound','Fieldnames are not unique between structures.') ;
|
|
sorted = 1 ;
|
|
end
|
|
|
|
if sorted
|
|
VAL = VAL(ind,:) ;
|
|
FN = FN(ind,:) ;
|
|
end
|
|
|
|
A = cell2struct(VAL, FN);
|
|
A = reshape(A, sz0) ; % reshape into original format
|
|
end
|