Variable Depth Struct Field Reference

조회 수: 18 (최근 30일)
James Mulhern
James Mulhern 2020년 2월 26일
댓글: Walter Roberson 2020년 5월 9일
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
Mohammad Sami
Mohammad Sami 2020년 2월 27일
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.

댓글을 달려면 로그인하십시오.

채택된 답변

Steven Lord
Steven Lord 2020년 2월 27일
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
James Mulhern
James Mulhern 2020년 2월 27일
It was the differnece between how I called fields
S = setfield(S,fields{:},some_val) %This works
S = setfield(S,fields,some_val) %This does not work
I forgot that cell{:} return a comma seperated list. I should remember because I get errors when I attempt to address a vecotor of cell with this call.

댓글을 달려면 로그인하십시오.

추가 답변 (2개)

Mohammad Sami
Mohammad Sami 2020년 2월 27일
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
David Saidman
David Saidman 2020년 5월 8일
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
Walter Roberson 2020년 2월 27일
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
James Mulhern
James Mulhern 2020년 2월 27일
Can you explain what cell expansion is and how it woulb be used with setfield?

댓글을 달려면 로그인하십시오.

카테고리

Help CenterFile Exchange에서 Structures에 대해 자세히 알아보기

제품


릴리스

R2015b

Community Treasure Hunt

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

Start Hunting!

Translated by