How can I use a variable number of structure fields as function arguments?

30 vues (au cours des 30 derniers jours)
Hello,
I have a structure that conatins a function handle and any number of other variables (in this case 4), like so:
MyStruct = struct('MyFun',@example,'a',1,'b',2,'c',5,'d',37);
where example is a simple function that takes in a variable number of arguments and displays them, like so:
function [] = example(varargin)
for n = 1:2:length(varargin)
disp(['Argument ' varargin{n} ' = ' num2str(varargin{n+1})])
end
I would like to call the function handle (in this case @example) using the variables stored in MyStruct, like so:
>> X = fieldnames(MyStruct)
X =
5×1 cell array
{'MyFun'}
{'a' }
{'b' }
{'c' }
{'d' }
>> MyStruct.MyFun(X{2}, MyStruct.(X{2}), X{3}, MyStruct.(X{3}), X{4}, MyStruct.(X{4}), X{5}, MyStruct.(X{5}))
Argument a = 1
Argument b = 2
Argument c = 5
Argument d = 37
Is there a way to do this for a structure with any number of fields/variables?
[Note: the function handle can point to one of several functions]
For example:
>> MyStruct.MyFun(X{2}, MyStruct.(X{2}), X{3}, MyStruct.(X{3}), . . . , X{999}, MyStruct.(X{999}))
Any help at all would be greatly appreciated!
Thanks!

Réponse acceptée

Stephen23
Stephen23 le 21 Mai 2020
Modifié(e) : Stephen23 le 21 Mai 2020
Use struct2cell and a comma-separated list:
>> X = fieldnames(MyStruct);
>> Y = struct2cell(MyStruct);
>> C = [X(2:end),Y(2:end)].'; % assumes that the function is the first field!
>> MyStruct.MyFun(C{:})
Argument a = 1
Argument b = 2
Argument c = 5
Argument d = 37
A more robust solution would be to not use positional input arguments for the function, but write it to accept the structure itself.
  3 commentaires
Steven Lord
Steven Lord le 21 Mai 2020
I second the "more robust solution" suggestion. Pass the struct into your functions and let the function itself extract the data it needs from the struct while ignoring the rest.
S = struct('x', 1, 'y', 2, 'z', 3);
timesY = @(x, S) x.*S.y; % ignores S.x and S.z
toPowerZ = @(q, S) q.^(S.z); % ignores S.x and S.y
In fact, if you want your function handles to "remember" S exactly as it existed when the function handle was created (rather than using a struct passed in at run-time), you can simplify this a bit more. If you want to change the S to which the function handles below refer you'll need to recreate those handles.
timesY2 = @(x) x.*S.y;
toPowerZ2 = @(q) q.^(S.z);

Connectez-vous pour commenter.

Plus de réponses (1)

Bill Tubbs
Bill Tubbs le 5 Avr 2023
Modifié(e) : Bill Tubbs le 5 Avr 2023
I recently discovered the function namedargs2cell (since r2019b) and use it for this purpose:
>> MyParams = struct('a',1,'b',2,'c',5,'d',37);
>> MyStruct = struct('Fun',@example,'Params',MyParams);
>> params = namedargs2cell(MyStruct.Params);
>> MyStruct.Fun(params{:})

Catégories

En savoir plus sur Structures dans Help Center et File Exchange

Community Treasure Hunt

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

Start Hunting!

Translated by