MATLAB: How to iterate through multiple structures

dynamic variable namesevalfieldnamesfor loopiterateloopstructstructures

I have a workspace filled with roughly 40 structs. I've attached a simplified version of the code I've written just to give you an idea of my approach(SEE CODE 1). The error I have been receiving is:
Attempt to reference field of non-structure array.
Error in example (line 11) xValues(i) = structNames{i}.Position(1);
But when I enter structNames{1} or (structNames{1}) in to the command window I get the value I expect: a1. When I type a1.Position(1) into the command window I also get the value I would expect: 5. But when I use structNames{1}.Position(1) it gives me the error message I mentioned before. When I use the ({}) syntax in the second value it works perfectly fine (SEE CODE 2). When running the code I've attached you have to delete one code to run the other. Help please 🙁
% ===== CODE 1 ==========
clear all;
a1.Position = [5 6] ;
a2.Position = [7 8] ;
b1.Position = [9 10] ;
b2.Position = [11 12] ;
a1.Time = [13];
a2.Time = [14];
b1.Time = [15];
b2.Time = [16];
holdStructNames = struct('a1',0,'a2',1,'b1',2,'b2',3);
structNames = fieldnames(holdStructNames);
holdFieldNames = struct('Position',0,'Time',1);
fieldNames = fieldnames(holdFieldNames);
for i = 1:numel(structNames)
xValues(i) = structNames{i}.Position(1);
end
%========== CODE 2 ==================
clear all;
a1.Position = [5 6] ;
a2.Position = [7 8] ;
b1.Position = [9 10] ;
b2.Position = [11 12] ;
a1.Time = [13];
a2.Time = [14];
b1.Time = [15];
b2.Time = [16];
holdStructNames = struct('a1',0,'a2',1,'b1',2,'b2',3);
structNames = fieldnames(holdStructNames);
holdFieldNames = struct('Position',0,'Time',1);
fieldNames = fieldnames(holdFieldNames);
for j = 1:numel(fieldNames)
timeANDposA(j) = a1.(fieldNames{j})(1);
timeANDposB(j) = b1.(fieldNames{j})(1);
end

Best Answer

The simplest solution is to create one non-scalar structure, like this:
% 1st row = "a"
% 2nd row = "b"
S(1,1).Position = 5:6 ;
S(1,2).Position = 7:8 ;
S(2,1).Position = 9:10 ;
S(2,2).Position = 11:12 ;
S(1,1).Time = 13;
S(1,2).Time = 14;
S(2,1).Time = 15;
S(2,2).Time = 16;
or equivalently
S = struct('Position',{5:6,7:8;9:10,11:12},'Time',{13,14;15,16})
and then accessing the data inside the structure is very simple
>> [S(1,:).Time] % "a" times
ans =
13 14
>> [S(2,:).Time] % "b" times
ans =
15 16
>> vertcat(S(2,:).Position) % all "b" positions
ans =
9 10
11 12
>> S(2,2).Position % second "b" position
ans =
11 12
Note how indexing can be used to access any element of the structure. This means that you can easily iterate over the structure in any way that you wish to:
>> for k = 1:size(S,2), S(1,k).Time, end % loop over the "a" times
ans =
13
ans =
14
You can also call arrayfun on a structure, for example to get the first elements of the "b" position vectors:
>> arrayfun(@(s)s.Position(1),S(2,:))
ans =
9 11