Clear Filters
Clear Filters

How to save an indefinite number of outputs to a struct

4 views (last 30 days)
I have a function that depending on the number of inputs I give it, it will give the same number of outputs. I want a way that I can save these outputs, regardless of how many there are, to a struct. This is what I have so far
varnames = cell(1,num_params); % Set a cell array with number of input as the length
varnames(:) = {'A'}; % Make each input 'A'
varnames = genvarname(varnames,'A'); % make each entry A1,A2,A3,...
Here num_params is the natural number of parameters I pass to it. I tried to add the lines
dis_obj.(varnames) = myfunc(paramlist{:});
dis_obj.(varnames(:)) = myfunc(paramlist{:});
dis_obj.(varnames{:}) = myfunc(paramlist{:});
but all of these games me errors. The goal here is to have my outputs be assigned to A1, A2, A3, ... where there are num_params outputs. Is there anyway to do this?

Accepted Answer

Stephen23 on 7 Nov 2022
Edited: Stephen23 on 7 Nov 2022
"Is there anyway to do this?"
Of course. But forcing pseudo-indices into structure fieldnames is much less efficient and more complex than simply using actual indices of a non-scalar structure. Using another cell array rather than a structure is probably the simplest and most efficient approach: a good rule of thumb is to keep data design as simple as reasonably possible.
Here I call NDGRID to demonstrate how it works, but of course you will call your own function:
A = {1:3,4:6,7:9} % example input cell array
A = 1×3 cell array
{[1 2 3]} {[4 5 6]} {[7 8 9]}
C = A; % preallocate output cell array
[C{:}] = ndgrid(A{:}) % call function
C = 1×3 cell array
{3×3×3 double} {3×3×3 double} {3×3×3 double}
Ah, very simple and very efficient code due to simpler data design.
Now with a structure array, also a reasonable approach:
S = struct('data',A); % preallocate structure array
[] = ndgrid(A{:}) % call function
S = 1×3 struct array with fields:
If you really want to follow your complex approach of hiding pseudo-indices in fieldnames, then CELL2STRUCT is one way (note how this just adds more complexity on top of simply using the cell array. You cannot avoid this because there is no comma-separated list syntax which allocates to different fields).
F = "A" + (1:numel(A));
inefficientDataDesign = cell2struct(C,F,2)
inefficientDataDesign = struct with fields:
A1: [3×3×3 double] A2: [3×3×3 double] A3: [3×3×3 double]
Read more:

More Answers (1)

Chris on 7 Nov 2022
Edited: Chris on 7 Nov 2022
Do you really need a struct? How about a map?
(dictionaries came out in 2022b and should work fine as well)
num_params = 3;
varnames = "A" + (1:num_params)' % String arrays are neat...
varnames = 3×1 string array
"A1" "A2" "A3"
% Make up some output...
out1 = table(rand(2,1),rand(2,1),'VariableNames',{'a','b'});
out2 = "a_string";
out3 = magic(3);
% Make a cell array (or a normal array if that's what your function does)
vals = {out1;out2;out3};
dis_obj = containers.Map(varnames, vals)
dis_obj =
Map with properties: Count: 3 KeyType: char ValueType: any
keys(dis_obj) % Get the names
ans = 1×3 cell array
{'A1'} {'A2'} {'A3'}
values(dis_obj) % and their values.
ans = 1×3 cell array
{2×2 table} {["a_string"]} {3×3 double}
dis_obj('A1') % Retrieve a value by varname
ans = 2×2 table
a b _______ _______ 0.54619 0.46966 0.81198 0.87781


Find more on Structures in Help Center and File Exchange




Community Treasure Hunt

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

Start Hunting!