Try dynamic field reference where you put a string in the parenthesis as seen on the line defining stuff.
S = struct('A', [1 2], 'B',[3 4 5]);
SNames = fieldnames(S);
for loopIndex = 1:numel(SNames)
stuff = S.(SNames{loopIndex})
end
I concur with Steve and Adam. Use cells. This syntax is right for people in other situations though!
There are three points I'd like to make here:
The reason you are getting an error in your above code is because of how you are indexing
SNames. The functionfieldnamesreturns a cell array of strings, so you have to use content indexing (i.e. curly braces) to access the string values. If you change the fourth line in your code to this:field = getfield(S, SNames{loopIndex});then your code should work without error.
As suggested by MatlabDoug, you can use dynamic field names to avoid having to use
getfield(which yields cleaner looking code, in my opinion).The suggestion from Adam to use a cell array instead of a structure is right on the mark. This is generally the best way to collect a series of arrays of different length into a single variable. Your code would end up looking something like this:
S = {[1 2], [3 4 5]}; % Create the cell array for loopIndex = 1:numel(S) % Loop over the number of cells array = S{loopIndex}; % Access the contents of each cell % Do stuff with array end
Concatenate everything along a fourth dimension, retrieve all indices and then squeeze the result back into a column vector. For example, if your structure array is S, you can do this:
A = cat(4, S.travelTime);
points = squeeze(A(60, 46, 75, :));
Benchmarking
Let's benchmark the possible solutions:
M = reshape(1:18, 2, 3, 3);
for k = 1:100
s(k).travelTime = mod(k, 6) * M;
end
tries = 1e4;
%// Vectorized solution
tic
for jj = 1:tries
A = cat(4, s.travelTime);
points = squeeze(A(1, 2, 1, :));
end
toc
%// For loop solution
tic
for jj = 1:tries
points = zeros(size(s));
for ii = 1:numel(s)
points(ii) = s(ii).travelTime(1, 2, 1);
end
end
toc
%// arrayfun solution
tic
for jj = 1:tries
Points = arrayfun(@(ii)s(ii).travelTime(1, 2, 1), 1:numel(s));
end
toc
The results are:
Elapsed time is 0.072367 seconds.
Elapsed time is 0.890323 seconds.
Elapsed time is 1.08522 seconds.
Not surprisingly, the vectorized solution is the fastest and an arrayfun solution is the slowest.
To copy a nice answer from In Matlab, how can I sort the order of a nested structure? (thanks @Gunther-Struyf!):
Points = arrayfun(@(ii) myStruct(ii).travelTime(60,46,75),1:numel(myStruct));
You may use fieldnames to get the data from the struct and then iteratively display the data using getfield function. For example:
structvariable = struct('a',123,'b',456,'c',789);
dataout = zeros(1,length(structvariable)) % Preallocating data for structure
field = fieldnames(a);
for i = 1:length(structvariable)
getfield(structvariable,field{i})
end
Remember, getfield gives data in form of cell, not matrix.
or you can use cellfun function:
% STRUCT - your structure
% tmp_nam - structure field names
% tmp_val - values for structure field names
tmp_nam = fieldnames(STRUCT);
tmp_val = cellfun(@(x)(STRUCT.(x)),tmp_nam,'UniformOutput',false);