Loren on the Art of MATLAB

Turn ideas into MATLAB

Note

Loren on the Art of MATLAB has been archived and will not be updated.

Concatenating structs

From time to time, I get asked or see queries about how to concatenate two struct arrays to merge the fields. There's even a section in the documentation covering this topic. I thought I'd show it here to help people out.

Contents

Example Data

Suppose I've got some system for which I have collected information on a couple of individuals, including their names and ages.

s1.name = 'fred';
s1.age = 42;
s1(2).name = 'alice';
s1(2).age = 29;

Later, I go back and collect the individual's heights (in cm).

s2.height = 170;
s2(2).height = 160;

It would be great to merge these arrays now.

s1
s2
s1 = 
1x2 struct array with fields:
    name
    age
s2 = 
1x2 struct array with fields:
    height

Let me collect the field names.

fn1 = fieldnames(s1);
fn2 = fieldnames(s2);
fn = [fn1; fn2];

Next, I ensure the fieldnames are unique.

ufn = length(fn) == unique(length(fn))
ufn =
     1

Next let me convert the data in my structs into cell arrays using struct2cell.

c1 = struct2cell(s1)
c2 = struct2cell(s2)
c1(:,:,1) = 
    'fred'
    [  42]
c1(:,:,2) = 
    'alice'
    [   29]
c2(:,:,1) = 
    [170]
c2(:,:,2) = 
    [160]

Next I merge the data from the 2 cell arrays.

c = [c1;c2]
c(:,:,1) = 
    'fred'
    [  42]
    [ 170]
c(:,:,2) = 
    'alice'
    [   29]
    [  160]

And finally, I construct the new struct using cell2struct.

s = cell2struct(c,fn,1)
s = 
1x2 struct array with fields:
    name
    age
    height

I can check the output now.

s(1)
s(2)
ans = 
      name: 'fred'
       age: 42
    height: 170
ans = 
      name: 'alice'
       age: 29
    height: 160

mergeStruct

Here's the function mergeStruct that I created to encapsulate the steps in this process, including some error checks.

dbtype mergeStruct
1     function sout = mergestruct(varargin)
2     %MERGESTRUCT Merge structures with unique fields.
3     
4     %   Copyright 2009 The MathWorks, Inc.
5     
6     % Start with collecting fieldnames, checking implicitly 
7     % that inputs are structures.
8     fn = [];
9     for k = 1:nargin
10        try
11            fn = [fn ; fieldnames(varargin{k})];
12        catch MEstruct
13            throw(MEstruct)
14        end
15    end
16    
17    % Make sure the field names are unique.
18    if length(fn) ~= length(unique(fn))
19        error('mergestruct:FieldsNotUnique',...
20            'Field names must be unique');
21    end
22    
23    % Now concatenate the data from each struct.  Can't use 
24    % structfun since input structs may not be scalar.
25    c = [];
26    for k = 1:nargin
27        try
28            c = [c ; struct2cell(varargin{k})];
29        catch MEdata
30            throw(MEdata);
31        end
32    end
33    
34    % Construct the output.
35    sout = cell2struct(c, fn, 1);

Do You Need to Merge struct data?

Do you ever need to merge data stored in structs when you gather new information? Or are your structs static in nature? If the information you collect is always the same sort of information, then you probably know the form of the structure when you start, even if all the data isn't available at first.

There is code on the File Exchange to concatenate structures; I confess I have not tried it, but it is highly rated. Does this post or the File Exchange contribution help your work?




Published with MATLAB® 7.9


  • print