Recursively create structure fields or (maybe) cell2struct

35 views (last 30 days)
ChrCoello on 22 Sep 2017
Edited: Stephen on 19 Jan 2018
Hey Matlab experts,
I am trying to be smart and create a structure as follows
ts.child1.child2 = 'sthg';
The depth of the structure is defined by the length of an array of cells and the field names are defined by the content of this array
fields = {'child1','child2'}
I don't want to "lock" the code with a fix number of for-loops as the numel(fields) can vary from 2 to N.
I have been testing a bit some ideas looking at the Answers in here, but I didn't find anything that didn't use a number of for loops defined by the numel(fields). I would like the idea below but adding the new fields in depth , not flat.
for iR = 1 : numel(fields), ts.(fields{iR}) = ''; end
ts =
struct with fields:
child1: ''
child2: ''
The result we want is
>> ts
struct with fields:
child1: [1×1 struct]
>> ts.child1
struct with fields:
child2: 'sthg'
The general idea is to read through a hierarchy (cell array) and create a structure from it
% Input : cell array
ans =
4×3 cell array
'White matter' '' ''
'' 'CC' ''
'' 'AC' ''
'' '' 'AC_AP'
% Expected output
ts = struct('name','white matter', 'children',[struct('name','CC','children',''),struct('name','AC','children',struct('name','AC_AP'))]);
Is cell2struct what I should be focusing on here ?
Thanks in advance for your help

Answers (1)

Stephen on 22 Sep 2017
Edited: Stephen on 19 Jan 2018
You might be interested in reading about non-scalar structures:
Method one: setfield and getfield:
Both setfield and getfield work with an arbitrary depth of nested structures (and indexing), all you need to do is supply each fieldname as an input (and when using setfield also with the data at the end):
>> S = struct();
>> S = setfield(S,'child1','child2','something');
>> S = setfield(S,'child1','hello1','world2','different');
>> S.child1.child2
ans = something
>> S.child1.hello1.world2
ans = different
In your case (where the fieldnames are in a cell array) you can supply them as a comma-separated list with the data variable at the end:
Method two: recursive function:
If you really are determined to do-it-yourself (which I do not recommend), then something like this should get you started. It adds all required substructures and allocates the data at the end:
function S = recfield(S,data,varargin)
S = recfun(S,data,varargin{1},varargin(2:end));
function S = recfun(S,data,fld,C)
if isempty(C)
S.(fld) = data;
if ~isfield(S,fld)
S.(fld) = struct();
S.(fld) = recfun(S.(fld),data,C{1},C(2:end));
And in use:
>> S = struct();
>> S = recfield(S,'something','child1','child2');
>> S = recfield(S,'different','child1','hello1','world2');
>> S.child1.child2
ans = something
>> S.child1.hello1.world2
ans = different
Note that it will simply overwrite any existing data in the same location.

Sign in to comment.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!