I am looking for a way to iterate through nested structs in MATLAB, with each sub-struct containing a varying number of fields, some of which may contain further nested structs. For example, I have the following struct A:
A.a.alpha=[2,3];
A.a.beta=[8,9,10];
A.a.delta.k=[5,6,7];
A.a.delta.m=1;
A.b.alpha=[22,32];
A.b.beta.n=3;
A.b.beta.o=[0,140];
Is there any way that I can automatically iterate through each of the end nodes of the struct A such that I can access A.a.alpha, A.a.beta, A.a.delta.k, A.a.delta.m, A.b.alpha, A.b.beta.n, and A.b.beta.o?
So far, I have seen nested for loops being used to access information that is a specific depth in (so accessing A.a.alpha, A.a.beta, A.b.alpha, but not A.a.delta.k, A.a.delta.m, A.b.beta.n, or A.b.beta.o), but my struct has those variable depths at which I need information access. I did consider using a "check if a sub-struct exists" method, but I can't figure out how to appropriately use that information to accomplish my goal here. Likewise, I also considered using a while loop that would stop at some A.end field but can't wrap my head around how to actually dig deeper into the variable depth sub-structs.
You can get the field names (or the data directly) using a recursive function, which calls itself on substructures.
Then you can use getfield()
to grab data out of nested structures, for example in your demo getfield( A, 'a', 'alpha' )
would return [2,3]
, but we can also do
fieldSplit = {'a','alpha'};
data = getfield( A, fieldSplit{:} );
So by using a recursive function to generate all of the nested field names, we can generate fieldSplit
for each subfield of your structure and pull out data at arbitrary depths.
Full demo with commented code for more details:
% Demo data
A = struct();
A.a.alpha=[2,3];
A.a.beta=[8,9,10];
A.a.delta.k=[5,6,7];
A.a.delta.m=1;
A.b.alpha=[22,32];
A.b.beta.n=3;
A.b.beta.o=[0,140];
% Get the nested field names
f = getNestedFields( A );
% Extract any data you want, or all of it
data = cell(1, numel(f));
for ii = 1:numel(f)
% Split the field name on the dot separators
fieldSplit = strsplit( f{ii}, '.' );
% Use getfield to get nested data
data{ii} = getfield( A, fieldSplit{:} );
end
function fields = getNestedFields( strct )
% Get the field names of this structure
fields = fieldnames( strct );
% Loop over the fields
for ii = 1:numel(fields)
if isstruct( strct.(fields{ii}) )
% This is a substructure, recursively fetch fields
% Replace this field name with subfield list
fields{ii} = strcat( fields{ii}, '.', getNestedFields(strct.(fields{ii})) );
else
% This is a non-struct field. Nest the name so that when we
% "flatten" things in a few lines we get back to a cell
fields{ii} = fields(ii);
end
end
% Flatten the names out to get all fields in one denested cell array
fields = [fields{:}];
end
Result: