Code covered by the BSD License  

Highlights from
CATSTRUCT

4.71429

4.7 | 21 ratings Rate this file 85 Downloads (last 30 days) File Size: 2.92 KB File ID: #7842

CATSTRUCT

by

 

13 Jun 2005 (Updated )

Concatenate/merge structures (v4.0, dec 2013).

| Watch this File

File Information
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] ;

Latest version: 4.0 (dec 2013)

MATLAB release MATLAB 7.12 (R2011a)
Other requirements Worked in all versions (6.5 and up) so far … For ancient versions (<7.0) you may need to replace a line in the code, as indicated.
Tags for This File   Please login to tag files.
Please login to add a comment or rating.
Comments and Ratings (30)
13 Aug 2014 Christian  
13 May 2014 maysam  
01 May 2014 Colin  
17 Mar 2014 Krzysztof

narginchk(1,Inf)
N = nargin ;

sorted = varargin { end };
if ischar(sorted)
narginchk(2,Inf)
assert (all (sorted == 'sorted'))
sorted = 1 ;
N = N-1 ;
else
sorted = 0 ;
end

11 Mar 2013 Jos (10584)

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

09 Mar 2013 Christophe

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

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

catstruct(struct('A',1),struct('A',2))

I get

A: 1

08 Mar 2013 Christophe  
06 Mar 2013 Jos (10584)

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

01 Mar 2013 Tor Inge Birkenes

@Jos
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
s1.name = 'fred';
s1.age = 42;
s1(2).name = 'alice';
s1(2).age = 29;
s2.height = 170;
s2(2).height = 160;
% Concentrate
A=catstruct(s1,s2)
% A is a 1x2 struct array
% with fields: name, age, height

% Add duplicate field
s1(1).height= '142';
s1(2).height = '195';
% Concentrate
A2=catstruct(s1,s2)
% 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.

28 Feb 2013 Jos (10584)

@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.

28 Feb 2013 Tor Inge Birkenes

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: http://blogs.mathworks.com/loren/2009/10/15/concatenating-structs/#11

I fixed it by changing
VAL = VAL(ind) ;
FN = FN(ind) ;
to
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

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});
end
sorted = 1;
end

17 Dec 2011 Wouter  
14 Feb 2011 grega  
10 Feb 2011 K E

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

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.
But

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  
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] ;

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
Thanks

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.

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...

X=[S1:S2:S3....]

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...

Updates
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

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

04 Dec 2013

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 ...

Contact us