Is there an alternative to eval in a struct?
15 views (last 30 days)
Show older comments
Hi,
I know that eval is evil, but in this particular case, I couldn't find any other way to do it, so I wanted to ask you if anyone comes up with a more efficient way.
The problem is, I need to define a struct, and structs inside that struct, and more structs inside that struct. I think it would be better to describe it (simplified) this way:
subject = {'subj_1','subj_2','subj_3'};
runs = {'rest','task1','task2','task3'};
roigroups = {'a','b','c'};
a = {'dlpfc','amyg'};
b = {'insula','postcg'};
c = {'thalamus','nucl_ruber'};
subjects = struct();
% The dirty way, assume that other structs defined previously:
for i = 1:length(subject)
for p = 1:length(runs)
for x = 1:length(roigroups)
for y = 1:eval(strcat('length(',roigroups{x},')'))
subjects.(subject{i}).(runs{p}).(roigroups{x}).(eval(strcat(eval('roigroups{x}'),'{y}'))) = struct();
end
end
end
end
It works really well, manually checked, but it's a pain to write and read. Is there a workaround for this type of task?
Accepted Answer
Matt J
on 22 Oct 2021
Edited: Matt J
on 22 Oct 2021
Your data organization seems like it should be reconsidered. In a struct, it doesn't make sense if different fields have essentially the same kind of contents. What I think you really want is a 2D or 3D struct array, something like
subject = {'subj_1','subj_2','subj_3'};
tasks = {'rest','task1','task2','task3'};
M=numel(subject);
N=numel(tasks);
a = struct('dlpfc',[],'amyg',[]);
b = struct('insula',[],'postcg',[]);
c = struct('thalamus',[],'nucl_ruber',[]);
[Subjects(1:M,1:N).a]=deal(a);
[Subjects(1:M,1:N).b]=deal(b);
[Subjects(1:M,1:N).c]=deal(c)
More Answers (2)
Akira Agata
on 22 Oct 2021
I believe it's better to arrange the data as a table rather than the deeply nested structure. How about the following?
subject = {'subj_1','subj_2','subj_3'};
runs = {'rest','task1','task2','task3'};
roigroups = {'a','b','c'};
a = {'dlpfc','amyg'};
b = {'insula','postcg'};
c = {'thalamus','nucl_ruber'};
[p,q,r] = ndgrid(subject, runs, [a,b,c]);
T = table(p(:),q(:),r(:),'VariableNames',{'subject','runs','roi'});
T.roigroups = repelem(roigroups',24,1);
T = movevars(T,'roigroups','Before','roi');
disp(T)
0 Comments
Steven Lord
on 22 Oct 2021
For most of what you're trying to do you could use setfield.
subject = {'subj_1','subj_2','subj_3'};
runs = {'rest','task1','task2','task3'};
roigroups = {'a','b','c'};
a = {'dlpfc','amyg'};
b = {'insula','postcg'};
c = {'thalamus','nucl_ruber'};
subjects = struct();
subjects = setfield(subjects, subject{1}, runs{2}, roigroups{3}, c{1})
% Checking
subjects.subj_1
subjects.subj_1.task1
For that last input probably I'd make a cell array of cell arrays out of a, b, and c.
D = {a, b, c};
subjects = setfield(subjects, subject{2}, runs{1}, roigroups{2}, D{2}{2})
subjects.subj_2.rest.b
0 Comments
See Also
Categories
Find more on Logical in Help Center and File Exchange
Products
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!