Variable Depth Struct Field Reference
18 Ansichten (letzte 30 Tage)
Ältere Kommentare anzeigen
James Mulhern
am 26 Feb. 2020
Kommentiert: Walter Roberson
am 9 Mai 2020
Hello,
I would like to programmatically reference different struct fields and I traditionally do that with the .() reference.
example_struct.(fieldname(i)) = some_data;
With my current project I would like to perform a similar reference, but the specific struct variable are of different depths. For example if I have the following struct
S.a.b.c = 1;
S.a.b.d = 2;
S.a.b.e = struct('f',[3 4],'g',5);
S.h = 50
I would like to do the equivalent of the following code, but dynamically reference the sub structs.
S.a.b.c = some_val(1);
S.a.b.e.f = some_val(2);
S.h = some_val(3);
I attempted the following code and it does not work.
fields_names = {'a.b.c';'a.b.e.f';'h'};
for i = 1:3
S.(field_names{i}) = some_val(i);
end
%I also tried
fields = {'a','b','c'};
S = setfield(S,fields,some_val(1));
My question is how do I reference these fields dynamically and adjust their value inside the same loop. I could create the following function, but it is not very robust.
function S = fucntion_name(in_Struct,field_names,depth,value)
switch depth
%Other cases omitted
case 3
S = in_Struct.(field_names(1)).(field_names(2)).(field_names(3)) = value;
end
end
Is there another way? Is there a way to pass the values into setfield() similarly to how multiple function varargin inputs can be pass as a single struct input?
1 Kommentar
Mohammad Sami
am 27 Feb. 2020
There are two potential solutions. You can look at the function subsref in Matlab
or write a recursive function which calls itself with one less argument, and a base case.
Akzeptierte Antwort
Steven Lord
am 27 Feb. 2020
You were very close with your setfield call. You need to turn your list of fields into a comma-separated list so that each element of the cell array fields is passed into setfield as a separate input.
fields = {'a','b','c'};
S = setfield(S,fields{:},42) % Call setfield with 5 inputs, the equivalent of
% S = setfield(S, 'a', 'b', 'c', 42)
S_dot_a_dot_b = S.a.b
One easy way to create the cell array fields from the character vector 'a.b.c' is to use split.
fields2 = split('a.b.c', '.')
Don't worry about the orientation of fields2 being different from fields. They will generate the same comma-separated list.
1 Kommentar
Weitere Antworten (2)
Mohammad Sami
am 27 Feb. 2020
You can use the subsref function to index into the struct. You need to create the variable s dynamicall.
To assign you can use the subasgn function
a = struct('b',struct('c',1));
s(1).type = '.';
s(1).subs = 'b';
s(2).type = '.';
s(2).subs = 'c';
out = subsref(a,s);
a = subsasgn(a,s,2);
a.b.c % value changed to 2
For example
function S = fucntion_name(in_Struct,field_names,value)
for i = 1:length(field_names)
s(i).type = '.';
s(i).subs = field_names{i};
end
S = subsasgn(in_Struct,s,value);
end
1 Kommentar
David Saidman
am 8 Mai 2020
that solved a lot of my problems. i made an overloaded setfield function
can also remove the loop by doing below, but its by no means better than Mohammad's loop
n = numel(field_names);
[s(1:n).type] = deal('.');
[s(1:n).subs] = field_names{:};
S = subsasgn(in_Struct,s,value)
Walter Roberson
am 27 Feb. 2020
Mohammad Sadi's approaches are fine. There is another class of approach though. You can split the string at periods, creating a cell array of character vectors. You can then use cell expansion to drop the list into a setfield call without having to special case the number of items you pass in.
2 Kommentare
Siehe auch
Kategorien
Mehr zu Structures finden Sie in Help Center und File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!