Search code examples
matlabstructurematlab-struct

Iterating over Matlab struct


I have a 1x1 Matlab struct with 15 fields

results = 

     RAR_no_compartments_2_0: [1x1 struct]
     RAR_no_compartments_2_1: [1x1 struct]
    RAR_no_compartments_2_10: [1x1 struct]
    RAR_no_compartments_2_11: [1x1 struct]
    RAR_no_compartments_2_12: [1x1 struct]
    RAR_no_compartments_2_13: [1x1 struct]
    RAR_no_compartments_2_14: [1x1 struct]
     RAR_no_compartments_2_2: [1x1 struct]
     RAR_no_compartments_2_3: [1x1 struct]
     RAR_no_compartments_2_4: [1x1 struct]
     RAR_no_compartments_2_5: [1x1 struct]
     RAR_no_compartments_2_6: [1x1 struct]
     RAR_no_compartments_2_7: [1x1 struct]
     RAR_no_compartments_2_8: [1x1 struct]
     RAR_no_compartments_2_9: [1x1 struct]

I'm trying to cycle through each of these in a for loop:

model_names=fieldnames(results); %get the names of each sub-struct
fieldname_dims=size(fieldnames(results)); %get dimensions of each struct
for i=1:fieldname_dims(1), %iterate over number of substructs
    name=model_names(i) %get the model name
    results.(name) %access the substruct
end

However Matlab returns the following error:

Argument to dynamic structure reference must evaluate to a valid field name.

Could somebody please explain to me why this is an invalid field name?


Solution

  • This is precisely what structfun is made for. It allows you to loop through all the fields of a structure.

    a = struct('a', 1, 'b', 2, 'c', 3);
    structfun(@(x)disp(x), a)
    
    1
    2
    3
    

    Alternately, you may consider storing an array of structures rather than a structure where the fields have numbers in them like you have. Any time that you are reliant on a fieldname to know ordering, it may be better to use a different data structure.

    For in your data, rather than having a fieldname of RAR_no_compartments_2_0 you'd simply assign the struct assigned to that field by index

    RAR_no_compartments(1) = results.RAR_no_compartments_2_0;
    RAR_no_compartments(2) = results.RAR_no_compartments_2_1;
    ...
    

    This way, rather than a 1 x 1 struct with 15 fields, you'd have a 1 x 15 array of structs which is much easier to deal with natively within MATLAB.

    Just a thought.