View License

Download apps, toolboxes, and other File Exchange content using Add-On Explorer in MATLAB.

» Watch video

Highlights from

4.7 | 30 ratings Rate this file 86 Downloads (last 30 days) File Size: 4.95 KB File ID: #7842 Version: 1.3



Jos (10584) (view profile)


13 Jun 2005 (Updated )

Concatenate/merge structures (v4.1, feb 2015).

| Watch this File

File Information

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: = 'Me' ;
      B.income = 99999 ;
      X = catstruct(A,B)
      % -> = '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: = '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).
To concatenate similar arrays of structs, you can use simple concatenation:
      A = dir('*.mat') ; B = dir('*.m') ; C = [A ; B] ;
Latest version: 4.0 (dec 2013)


This file inspired Structable and Lynx Matlab Toolbox.

MATLAB release MATLAB 8.3 (R2014a)
MATLAB Search Path
Tags for This File   Please login to tag files.
Please login to add a comment or rating.
Comments and Ratings (43)
28 Jul 2016 Alan

Alan (view profile)

01 May 2016 Jos (10584)

Jos (10584) (view profile)

@arnold Simply use any of the basic concatenation functions, for instance: z = cat(2, x.a, y.a]

If your structures are named like x1, x2, x3, you really need to reconsider your variable naming approach. You would be better off when you stored them in an array of structures:
z.a = cat(x(:).a)

Comment only
29 Apr 2016 arnold

arnold (view profile)

I understand that it could lead to conflicts but do you have a better idea on how to append data to structures if the data format actually fits?
I have many usage scenarios where it would make sense to use structures for different variables with congruent data format but it then turns out to be quite cumbersome to simply consolidate them. Example: measurement-data

Comment only
28 Apr 2016 Jos (10584)

Jos (10584) (view profile)

@arnold, that behaviour would be quite arbitrary and depending on the contents of the field which may differ between the two structures. Example:
a.x = 'test', b.x = magic(3), catstruct(a,b) ??

Comment only
26 Apr 2016 arnold

arnold (view profile)

any chance you can add the ability to append data if fieldnames already exist?

catstruct(a,a) then would result in a new struct with the same fields as a but double the entries in each field.

Comment only
09 Feb 2016 Gad Molkho

Thanks a lot!

27 Nov 2015 Nugraha

Thank you

14 Oct 2015 Robert

Robert (view profile)

Great function! Greetings from Croatia

17 Sep 2015 David MERCIER

08 Sep 2015 David Young

David Young (view profile)

18 Jul 2015 Anton Semechko

Anton Semechko (view profile)

14 May 2015 Solenostomus

Great function, but not versatile enough for what I wanted. I also use structs for configuration settings, but my structs are nested (structs of structs of structs of values).
So I needed to add some recursion:
[UFN2,ind2] = unique(FN, 'last') ;
[UFN1,ind1] = unique(FN, 'first') ;

if numel(UFN2) ~= numel(FN),
%warning('catstruct:DuplicatesFound','Fieldnames are not unique between structures.') ;
sorted = 1 ;

if sorted,
VAL2 = cell(numel(ind2),1);
for n=1:numel(ind1)
v1 = VAL(ind1(n),:);
v2 = VAL(ind2(n),:);
if iscell(v1) && numel(v1)==1 && isstruct(v1{1}) && iscell(v2) && numel(v2)==1 && isstruct(v2{1})
v = cell(1,1); v{1} = catstruct(v1{1}, v2{1});
VAL2(n) = v;
VAL2(n) = v2;
FN = FN(ind2,:) ;

A = cell2struct(VAL2, FN);

This edit only works when 2 structs are combined, which is fine for me (the default config struct and the user defined one), but it's not general because the calls to unique() only identify the first and last occurrence.

This would need more work for the general case and I may have broken some other use cases.

05 Jan 2015 Brad Stiritz

Great utility, thanks for providing this. Please be aware that your current version 4.0 generates two warnings in R2014b that nargchk() will be removed in a future MATLAB version.

13 Aug 2014 Christian

13 May 2014 Sam

Sam (view profile)

01 May 2014 Colin

Colin (view profile)

17 Mar 2014 Krzysztof

N = nargin ;

sorted = varargin { end };
if ischar(sorted)
assert (all (sorted == 'sorted'))
sorted = 1 ;
N = N-1 ;
sorted = 0 ;

11 Mar 2013 Jos (10584)

Jos (10584) (view profile)

Thanks Christophe for pointing out the changed behavior of unique! I will fix this soon.

Comment only
09 Mar 2013 Christophe

One solution to restore compatibility across MATLAB version would be to substitute line 124:
[UFN,ind] = unique(FN) ;
if verLessThan('matlab','8.1')
[UFN,ind] = unique(FN) ;
[UFN,ind] = unique(FN,'legacy') ;

Comment only
08 Mar 2013 Christophe

This is a very useful function!

Unfortunately, it seems that the release of MATLAB 2013a breaks its behavior. They have changed the behavior of the function unique and now when I type


I get

A: 1

Comment only
08 Mar 2013 Christophe

06 Mar 2013 Jos (10584)

Jos (10584) (view profile)

@Tor Inge Birkenes
I see your problem! An update is being submitted ...

Comment only
01 Mar 2013 Tor Inge BL

If its inteded it is of course all right, but it feels inconsistent to me.
I care about this because I am using structs to store configuration parameters and use your function to merge standard and user defined values. In this case it is expected to have duplicate fields. As you point out this is outside the intended use of the function, but it still works great.

In case my explanation of the problem was insufficient i include concrete example this time:

% Defining struct arrays = 'fred';
s1.age = 42;
s1(2).name = 'alice';
s1(2).age = 29;
s2.height = 170;
s2(2).height = 160;
% Concentrate
% A is a 1x2 struct array
% with fields: name, age, height

% Add duplicate field
s1(1).height= '142';
s1(2).height = '195';
% Concentrate
% A2 is a struct with fields:
% name, age, height

I is the dimension difference (1x2 vs 1x1) that i find inconsistent, and I did not expect based on the warning "Warning: Duplicate fieldnames found. Last value is used and fields are sorted". I would expect an 1x2 array where the field values from s2 were used when there are conflict, as the function does with the first field in the structure.

Comment only
28 Feb 2013 Jos (10584)

Jos (10584) (view profile)

@Tor Inge Birkenes
This behaviour is intended. CATSTRUCT merges separate structures containing different(!) field names into 1. For instance, it works perfectly for the initial example given in Loren's blog.

Comment only
28 Feb 2013 Tor Inge BL

Great function!

I found a bug when concentrating struct arrays with common fields.
Then only the first struct was concentrated, the rest was discarded.
For an example add height-field to s1 in the example here, and concentrate:

I fixed it by changing
VAL = VAL(ind) ;
FN = FN(ind) ;
VAL = VAL(ind,:,:) ;
FN = FN(ind,:,:) ;
at line 88-89. Seems to work nicely.

21 Feb 2012 Wintersprite

simple to use, but what I really wanted to do was to gather up 5 structures and put them into one structure variable, whereas this script flattened my existing structures.

17 Dec 2011 Wouter

Wouter (view profile)

I also needed to concatenate arrays and cells at the leaf nodes in the case when the fieldnames match. This can be done by slightly adjusting the code as:
if numel(UFN) ~= numel(FN),
warning('catstruct:DuplicatesFound','Duplicate fieldnames found. Fields are merged and sorted.') ;
Nd = numel(unique(j));
for i=1:Nd
idx = find(j==unique(j(i)));
[nr,nc] = cellfun(@size, VAL(idx));
% comment if fields are not required to be equal in size:
if diff(nr) || diff(nc);error(['Duplicate field ' FN{idx(1)} ' does not have the same size for all structures.']);end
[p,rcm] = min([nc(1) nr(1) 2]);
% concatenate rows as rows, colums as colomns and matrices along 2nd dimension.
VAL{idx(end)} = cat(min(rcm,2),VAL{idx});
sorted = 1;

Comment only
17 Dec 2011 Wouter

Wouter (view profile)

14 Feb 2011 grega

grega (view profile)

10 Feb 2011 K E

K E (view profile)

Should be standard in Matlab

17 Jul 2009 Scott Otterson

This works well. I agree with Jeremy that recursive concatenation would be an advantage. It would also be useful to concatenate arrays and cells at the leaf nodes in the case when the fieldnames match (I've had to do this many times).

But it works for what I'm doing at the moment. Thanks!

08 Apr 2009 Gabriel Akira Schreiber

great work, may the sun always shine on you.

22 Jan 2009 Jeremy

Jeremy (view profile)

Nice work, just one comment:
I just noticed that when merging two structures, the fact that any dissimilar fields in the FIRST level are merged, but dissimilarities in subsequent levels are lost: e.g.

s1.a = 1;
s1.b = 2;

s2.a = 101;

s3 = catstruct(s1,s2) gives s3.a = 101, s3.b = 2.

s1.A.a = 1;
s1.A.b = 2;

s2.A.a = 101;

gives s3.A = a : 101.
i.e. we lose field b. I kind of understand the logic, i.e. that it is now field A that is being overwritten by a new field A, so that a depth=1 merge has occurred, but for anyone looking to do a true merge-style operation, this means needing to loop though each level... any plans to change this?

11 Dec 2008 Daniel

Daniel (view profile)

29 Sep 2008 Jos (the author)

To Benny. Catstruct does work on structures with non-numeric fields (see the example). You're after simple concatenation, for which you do not need catstruct at all ...

a = dir('*.mat')
b = dir('*.txt')
c = [a ; b] ;

Comment only
29 Sep 2008 Benny .

Good job. It would be very usefull if it also worked on general structures, not only those containing numerical matrices only, e.g.

a = dir('*.txt');
b = dir('*.mat');
c = catstruct(a,b);

04 Aug 2008 Piotr .

Very useful function!

28 May 2008 Maziar Hashemi-Nezhad

Perfect basic program

21 Feb 2008 Hoi Wong

Cool program. I can't imagine why MATLAB wouldn't have something like this built-in, but you filled the gap!

21 Sep 2007 Jos (the author)

new version 2.0 (sep 2007). A bug was removed which ocured when fields contained cell arrays.

Comment only
04 May 2007 Jingzhao Ou

A very useful script!

16 Apr 2007 Nadaraja Pillai

Hi ,
It is possible to concates the structure simply using collon... For example...


It will do it...

28 Oct 2006 Paolo de Leva

This function is a must for people using structures. I wonder why MATLAB doesn't allow (as far as I know) structure concatenation using the [S1, S2] syntax, when the two structures have different fields. The builtin function STRUCT can't add fields to an existing structure...

21 Jun 2006

added semi-colons

24 Sep 2007

removed bug when delaing with fields containing cell arrays

24 Sep 2007

add keywords

16 Sep 2008

added identifiers

06 Mar 2013 1.1

now deals correctly with arrays of structures (thanks to Tor Inge Birkenes for pointing out this problem)

04 Dec 2013 1.2

Due to changes implemented by The Mathworks in their set functions, I had to explicitly tell unique to return the last occurrence of a value in a set ...

04 Feb 2015 1.3

changed number of input arguments check to accommodate future releases. Probably this function will no longer work anymore in older releases :-(

Contact us