How to add multiple variables to a structure

I have a cell ('varNames') containing variable names that I want to add to a structure ('s'). I am currently acheiving this using the evaluate command as:
for i=1:length('varNames')
eval(strcat('s.',varNames{i},'=',varNames{i},';'));
end
However, I want to avoid using the evaluate command, as I will be using this code inside a parfor loop to speed up Simulink simulations. I have so far tried the solution here with a method to extract variable names described here as:
getname = @(x) inputname(1);
makeStruct = @(x) struct(getname(x),x);
s = cellfun(makeStruct, varNames);
But it just adds the variable names to the structure 's', not the actual variables. The variables are structures themseleves generated by the ToWorkspace blocks of Simulink.

댓글 수: 1

Stephen23
Stephen23 2023년 1월 13일
편집: Stephen23 2023년 1월 13일
EVAL is completely unnecessary, the approaches you link to are... very complex.
As Jiri Hajek shows, all you need is INPUTNAME() and this:

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

답변 (1개)

Jiri Hajek
Jiri Hajek 2023년 1월 13일

1 개 추천

Hi, eval is indeed completely unnecessary for your assignment.To create a new field in a structure, for which you have a name defined by a character vector or a string, use parentheses.
s.(newFieldName) = newData;
The newData may of course by a struct. The newFieldName must be string or character vector, which you may supply in a variable, e.g. varNames{i} as in your example.

댓글 수: 7

Afzal
Afzal 2023년 1월 13일
If I remove the evaluate, and run s.varNames{i} = varNames{i}, it just assigns the variable name to s, not the variable.
If I remove the evaluate, and run s.varNames{i} = varNames{i}, it just assigns the variable name to s, not the variable.
That's correct. But if you compare that command and the one posted by @Jiri Hajek you'll see that Jiri's command includes parentheses and the one you wrote does not. Those parentheses are very important to use dynamic field names functionality.
f = 'abc';
s.f = 1 % Write to a field named f
s = struct with fields:
f: 1
s.(f) = 2 % Write to a field whose name is stored in the variable f
s = struct with fields:
f: 1 abc: 2
s.('hello') = 3 % You can also use text literals
s = struct with fields:
f: 1 abc: 2 hello: 3
s.("world") = 4
s = struct with fields:
f: 1 abc: 2 hello: 3 world: 4
Afzal
Afzal 2023년 1월 13일
I want to avoid having to do s.varName{1} = newData1; s.varName{2} = newData2, and so on. I don't want to store the variable name in the structure, but the variable itself.
Stephen23
Stephen23 2023년 1월 13일
"I want to avoid having to do s.varName{1} = newData1; s.varName{2} = newData2, and so on."
So don't do that. No one here is advising you to do that.
Jiri Hajek and everyone else here is advising you to use dynamic fieldnames, using parentheses.
"I don't want to store the variable name in the structure, but the variable itself."
Jiri Hajek's code does not store the variable name in the structure, their code stores the variable itself.
Afzal
Afzal 2023년 1월 13일
편집: Afzal 2023년 1월 13일
Here's how I understand what Jiri Hajek has said to apply to my situation. I've added parenthese as well, but the structure s just contains the strings. 'a', 'b', 'c'. I want it to contain the values of the variables (1, 2, 3). I need to use a for loop, as there are many variables, and don't want to assign each variable to the structure without a loop.
a=1; b=2; c=3;
varNames={'a','b','c'};
for i=1:length(varNames)
s.(varNames{i})=varNames{i};
end
You're going to need to use eval or save and load to do it this way.
But let's take a step back. You say you have a lot of variables; how did you get those into your workspace in the first place? There may be ways to modify that code to avoid creating those variables.
One example is if you're calling load without an output modify that call to call it with an output. Let's set up some sample data.
cd(tempdir)
x = 1;
y = 'two';
z = magic(3);
save mymatfile.mat x y z
Now let's clear the workspace and confirm that it's clear.
clear all
whos
You could load without an output:
load mymatfile.mat
whos
Name Size Bytes Class Attributes x 1x1 8 double y 1x3 6 char z 3x3 72 double
Or you could call load with an output. Note that x, y, and z are not loaded as individual variables. They're loaded as fields of the struct named data.
clear all
data = load('mymatfile.mat')
data = struct with fields:
x: 1 y: 'two' z: [3×3 double]
whos
Name Size Bytes Class Attributes data 1x1 590 struct
"...as there are many variables, and don't want to assign each variable to the structure without a loop."
That is a sign that your data design probably need to be improved. Instead of creating lots of separate variables, you should probably create one array in the first place. For example, if you are LOADing data from a MAT file, then simply LOAD into an output variable (which is a scalar structure):
S = load(..);
If you only have a handful of variables, then you could use a function like this (untested):
function S = mystruct(varargin)
S = struct();
for k = 1:nargin
S.(inputname(k)) = varargin{k};
end
end

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

카테고리

도움말 센터File Exchange에서 Simulink Environment Customization에 대해 자세히 알아보기

제품

릴리스

R2020b

질문:

2023년 1월 13일

댓글:

2023년 1월 14일

Community Treasure Hunt

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

Start Hunting!

Translated by