Is there an alternative to eval in a struct?

15 次查看(过去 30 天)
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
Unrecognized function or variable 'tasks'.
It works really well, manually checked, but it's a pain to write and read. Is there a workaround for this type of task?
  4 个评论
Akira Agata
Akira Agata 2021-10-22
Still not working.
As shown below, error occurs in the line "subjects.(subjects{i})~" .
subjects = {'subj_1','subj_2','subj_3'};
tasks = {'rest','task1','task2','task3'};
roigroups = {'a','b','c'};
a = {'dlpfc','amyg'};
b = {'insula','postcg'};
c = {'thalamus','nucl_ruber'};
% The dirty way, assume that other structs defined previously:
for i = 1:length(subjects)
for p = 1:length(tasks)
for x = 1:length(roigroups)
for y = 1:eval(strcat('length(',roigroups{x},')'))
subjects.(subjects{i}).(tasks{p}).(roigroups{x}).(eval(strcat(eval('roigroups{x}'),'{y}'))) = struct();
end
end
end
end
Unable to perform assignment because dot indexing is not supported for variables of this type.
Yasir Çatal
Yasir Çatal 2021-10-22
Sorry, I edited now so that it works. Should've checked before, sorry about that.

请先登录,再进行评论。

采纳的回答

Matt J
Matt J 2021-10-22
编辑:Matt J 2021-10-22
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)
Subjects = 3×4 struct array with fields:
a b c
  5 个评论
Matt J
Matt J 2021-10-22
编辑:Matt J 2021-10-22
Okay, but is there an intuitive way to see which task/roi etc. belong to which subject?
In your post, all subjects share the same tasks and roigroups. That's why I think an array makes more sense.
for example, I need to exclude some subjects, and when I do that, I don't want every subsequent subject to go up one row and mess everything.
You would have to show an example of "mess everything". Why couldn't you extract a subset of Subjects using integer indices? e.g.,
subset=Subjects([1,5,7],:)
Yasir Çatal
Yasir Çatal 2021-10-22
Thanks to everyone that involved, I guess I should go with subsets.

请先登录,再进行评论。

更多回答(2 个)

Akira Agata
Akira Agata 2021-10-22
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)
subject runs roigroups roi __________ _________ _________ ______________ {'subj_1'} {'rest' } {'a'} {'dlpfc' } {'subj_2'} {'rest' } {'a'} {'dlpfc' } {'subj_3'} {'rest' } {'a'} {'dlpfc' } {'subj_1'} {'task1'} {'a'} {'dlpfc' } {'subj_2'} {'task1'} {'a'} {'dlpfc' } {'subj_3'} {'task1'} {'a'} {'dlpfc' } {'subj_1'} {'task2'} {'a'} {'dlpfc' } {'subj_2'} {'task2'} {'a'} {'dlpfc' } {'subj_3'} {'task2'} {'a'} {'dlpfc' } {'subj_1'} {'task3'} {'a'} {'dlpfc' } {'subj_2'} {'task3'} {'a'} {'dlpfc' } {'subj_3'} {'task3'} {'a'} {'dlpfc' } {'subj_1'} {'rest' } {'a'} {'amyg' } {'subj_2'} {'rest' } {'a'} {'amyg' } {'subj_3'} {'rest' } {'a'} {'amyg' } {'subj_1'} {'task1'} {'a'} {'amyg' } {'subj_2'} {'task1'} {'a'} {'amyg' } {'subj_3'} {'task1'} {'a'} {'amyg' } {'subj_1'} {'task2'} {'a'} {'amyg' } {'subj_2'} {'task2'} {'a'} {'amyg' } {'subj_3'} {'task2'} {'a'} {'amyg' } {'subj_1'} {'task3'} {'a'} {'amyg' } {'subj_2'} {'task3'} {'a'} {'amyg' } {'subj_3'} {'task3'} {'a'} {'amyg' } {'subj_1'} {'rest' } {'b'} {'insula' } {'subj_2'} {'rest' } {'b'} {'insula' } {'subj_3'} {'rest' } {'b'} {'insula' } {'subj_1'} {'task1'} {'b'} {'insula' } {'subj_2'} {'task1'} {'b'} {'insula' } {'subj_3'} {'task1'} {'b'} {'insula' } {'subj_1'} {'task2'} {'b'} {'insula' } {'subj_2'} {'task2'} {'b'} {'insula' } {'subj_3'} {'task2'} {'b'} {'insula' } {'subj_1'} {'task3'} {'b'} {'insula' } {'subj_2'} {'task3'} {'b'} {'insula' } {'subj_3'} {'task3'} {'b'} {'insula' } {'subj_1'} {'rest' } {'b'} {'postcg' } {'subj_2'} {'rest' } {'b'} {'postcg' } {'subj_3'} {'rest' } {'b'} {'postcg' } {'subj_1'} {'task1'} {'b'} {'postcg' } {'subj_2'} {'task1'} {'b'} {'postcg' } {'subj_3'} {'task1'} {'b'} {'postcg' } {'subj_1'} {'task2'} {'b'} {'postcg' } {'subj_2'} {'task2'} {'b'} {'postcg' } {'subj_3'} {'task2'} {'b'} {'postcg' } {'subj_1'} {'task3'} {'b'} {'postcg' } {'subj_2'} {'task3'} {'b'} {'postcg' } {'subj_3'} {'task3'} {'b'} {'postcg' } {'subj_1'} {'rest' } {'c'} {'thalamus' } {'subj_2'} {'rest' } {'c'} {'thalamus' } {'subj_3'} {'rest' } {'c'} {'thalamus' } {'subj_1'} {'task1'} {'c'} {'thalamus' } {'subj_2'} {'task1'} {'c'} {'thalamus' } {'subj_3'} {'task1'} {'c'} {'thalamus' } {'subj_1'} {'task2'} {'c'} {'thalamus' } {'subj_2'} {'task2'} {'c'} {'thalamus' } {'subj_3'} {'task2'} {'c'} {'thalamus' } {'subj_1'} {'task3'} {'c'} {'thalamus' } {'subj_2'} {'task3'} {'c'} {'thalamus' } {'subj_3'} {'task3'} {'c'} {'thalamus' } {'subj_1'} {'rest' } {'c'} {'nucl_ruber'} {'subj_2'} {'rest' } {'c'} {'nucl_ruber'} {'subj_3'} {'rest' } {'c'} {'nucl_ruber'} {'subj_1'} {'task1'} {'c'} {'nucl_ruber'} {'subj_2'} {'task1'} {'c'} {'nucl_ruber'} {'subj_3'} {'task1'} {'c'} {'nucl_ruber'} {'subj_1'} {'task2'} {'c'} {'nucl_ruber'} {'subj_2'} {'task2'} {'c'} {'nucl_ruber'} {'subj_3'} {'task2'} {'c'} {'nucl_ruber'} {'subj_1'} {'task3'} {'c'} {'nucl_ruber'} {'subj_2'} {'task3'} {'c'} {'nucl_ruber'} {'subj_3'} {'task3'} {'c'} {'nucl_ruber'}

Steven Lord
Steven Lord 2021-10-22
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})
subjects = struct with fields:
subj_1: [1×1 struct]
% Checking
subjects.subj_1
ans = struct with fields:
task1: [1×1 struct]
subjects.subj_1.task1
ans = struct with fields:
c: 'thalamus'
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 = struct with fields:
subj_1: [1×1 struct] subj_2: [1×1 struct]
subjects.subj_2.rest.b
ans = 'postcg'

类别

Help CenterFile Exchange 中查找有关 Structures 的更多信息

产品

Community Treasure Hunt

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

Start Hunting!

Translated by