MATLAB Answers

0

Is it possible to concatenate structures with the same fields in to one super structure?

Asked by Duncan Wright on 5 Nov 2017
Latest activity Edited by Stephen Cobeldick on 2 Oct 2019
I have structures c and c1, each contain 55 fields with the same names.
The field dimensions differ slightly in the x domain (ie):
c.E: [68×120 single]
c.N_z_cross: [68×120 single]
c.N_z_long: [68×120 single]
and
c1.E: [84×120 single]
c1.N_z_cross: [84×120 single]
c1.N_z_long: [84×120 single]
ideally I would like to create a structure that contains both continually (ie)
full_data.E: [152×120 single]
full_data.N_z_cross: [152×120 single]
full_data.N_z_long: [152×120 single]
Is there anyway to do this without manually concatenating each variable?
Thanks in advance.

  1 Comment

"Is it possible to concatenate structures": yes, it is certainly possible to concatenate structures together:
[struct1,struct2]
will concatenate two structures together. But what you describe in the body of your question is how to to concatenate structure fields together, not the structures themselves. Both of these things are possible, but require very different code.

Sign in to comment.

3 Answers

Stephen Cobeldick 님의 답변 5 Nov 2017
Stephen Cobeldick 님이 편집함. 5 Nov 2017
 채택된 답변

>> S.data = 1;
>> S.year = 2017;
>> T.data = 2;
>> T.year = 1988;
>> Z = cell2struct(cellfun(@vertcat,struct2cell(S),struct2cell(T),'uni',0),fieldnames(S),1);
>> Z.data
ans =
1
2
>> Z.year
ans =
2017
1988
It would be perfect if structfun accepted multiple input structures, but sadly it only works on one input struct :(

  3 Comments

What an operational disaster. Someone at MathWorks needs to fix this so data arrays can be merged directly when combining structure fields.
Note that this concept assumes that the fields are in the same order. If they are not, then use orderfields first, or use Jan's solution which relies only on the fields' names (and not their order).

Sign in to comment.


Jan 님의 답변 5 Nov 2017
Stephen Cobeldick 님이 편집함. 2 Oct 2019

Or with a loop:
function S = CatStructFields(S, T, dim)
fields = fieldnames(S);
for k = 1:numel(fields)
aField = fields{k}; % EDIT: changed to {}
S.(aField) = cat(dim, S.(aField), T.(aField));
end
Then:
full_data = CatStructFields(c, c1, 1)

  3 Comments

+1 simple and efficient. Can be generalized to any number of structures:
function S = CatStructFields(dim, varargin)
F = cellfun(@fieldnames,varargin,'uni',0);
assert(isequal(F{:}),'All structures must have the same field names.')
T = [varargin{:}];
S = struct();
F = F{1};
for k = 1:numel(F);
S.(F{k}) = cat(dim,T.(F{k}));
end
end
I had the same question, but I'm getting an error from this code, which is based on what is above, written for two structures Chain1 and Chain2 that have the same fields in the same order.
fields = fieldnames(Chain1);
for k = 1:numel(fields)
aField = fields(k);
fit.(aField) = cat(1, Chain1.(aField), Chain2.(aField));
end
Error: Argument to dynamic structure reference must evaluate to a valid field name.
Basically, it does not accept Chain1.(aField) - or using aField cell to refer to a structure field in general - as valid syntax.
@Murat Aydin: the error is easy to indentify: fieldnames returns a cell array of character vectors, but the dynamic fieldname syntax requires a character vector. So you just need to use the correct indexing to get the character vector out of the cell array:
aField = fields{k};

Sign in to comment.


Ba Mo 님의 답변 24 Jul 2019
Ba Mo 님이 편집함. 24 Jul 2019

my_struct_fields = fieldnames(my_struct1);
super_struct=arrayfun(@(i) [my_struct1.(my_struct_fields{i});my_struct2.(my_struct_fields {i})],[1:numel(my_struct_fields)]','un',0);
my_dirty_trick = [my_struct_fields,super_struct]';
final_struct = struct(my_dirty_trick{:});
Thank you for officially accepting my answer

  0 Comments

Sign in to comment.