How to make dynamic variable names (A1, A2, ..., An) with "for" loop? Using "eval" "num2str"?

838 Ansichten (letzte 30 Tage)
Hello community,
my knowledge of Matlab is limited, I admit it. So, I am sorry if I am going to make mistakes.
I have to create a series of variable using a "for" loop.
I make this:
for i=1:3
eval(['A' num2str(i) '= i'])
end
and it works well, it makes 3 variables A1, A2, A3.
But I need to use this variables to make other variables B1, B2, B3 where Bi=Ai*i. So I should have B1=A1*1=1, B2=A2*2=2*2=4, B3=A3*3=3*3=9
I tried something like this:
for i=1:3
eval(['A' num2str(i) '= i'])
eval(['B' num2str(i) '= 'A' num2str(i) '*i])
end
but it gives me error and it doesn't work. Of course I simplified things, the real code is a bt more complicated but I need to know the basics of how this could work.
Thank you
  11 Kommentare
Stephen23
Stephen23 am 19 Jan. 2022
Bearbeitet: Stephen23 am 19 Jan. 2022
"With dynamic naming you can call them pic1.png, pic2.png, pic3.png, pic4.png, etc and have them automatically saved in the directory of your choosing."
No, you are mixing up filenames with the names of variables in the MATLAB workspace. Two totally different things.
Mixing up unrelated topics will not make it easy to understand or use MATLAB. Or any programming language, for that matter.
Also note that MATLAB variable names cannot have the dot character in them, so your example variable names are invalid and would not work, even though you incorrectly state that "you can call them pic1.png, pic2.png, pic3.png, pic4.png". This should also give you a hint as to one reason why your approach of dynamically naming variables based on a filenames is a really bad idea (hint: consider all of the Unicode characters that are valid in filenames. Are they also valid in variable names? hint: no).
"Using indexing, how can you call them pic1, pic2, pic3, and pic4 in order to automatically increment and save each photo?"
Very easily: the two main approaches are:
  • read a list of existing files and alter the names (e.g. append a suffix, change the extension).
  • generate the filenames (e.g. using SPRINTF).
Both of these methods generally use indexing, as shown in the MATLAB documentation here:
and also on thousands and thousands and thousands of threads on this forum (none of which require dynamic variable names, even if their filenames increment numbers just as you show), because, surprisingly, importing and exporting file data is a very common topic that people want to achieve. Using indexing. Because that is how MATLAB works.
Steven Lord
Steven Lord am 19 Jan. 2022
I think of dynamic file names as somewhat different from dynamic variable names, as the file names are usually themselves data (passed into a function that reads the file contents then returns a variable whose name is not necessarily tied to the file name, or performs some other operation on the file.)
t = fullfile(tempdir, 'writeASeriesOfFiles');
if ~isfolder(t)
mkdir(t);
end
dir(t) % Nothing in this directory yet
. ..
for k = 1:5
fn = fullfile(t, "file" + k + ".txt");
% Now use fn as data in several function calls
fclose(fopen(fn, 'wt')); % Open and immediately close the file
doesItExist = isfile(fn);
if doesItExist
fprintf("File %s does exist!\n", fn)
else
fprintf("File %s does NOT exist!\n", fn)
end
end
File /tmp/writeASeriesOfFiles/file1.txt does exist! File /tmp/writeASeriesOfFiles/file2.txt does exist! File /tmp/writeASeriesOfFiles/file3.txt does exist! File /tmp/writeASeriesOfFiles/file4.txt does exist! File /tmp/writeASeriesOfFiles/file5.txt does exist!
dir(t)
. .. file1.txt file2.txt file3.txt file4.txt file5.txt

Melden Sie sich an, um zu kommentieren.

Akzeptierte Antwort

Stephen23
Stephen23 am 12 Jan. 2016
Bearbeitet: Stephen23 am 19 Jun. 2019
  2 Kommentare
Giovanni Barbarossa
Giovanni Barbarossa am 27 Jun. 2018
Hello, I have a similar need deriving from what it seems to be a limitation of the Classification Learner app. I am generating a cell array of tables with my program and want to try each of the tables as training features in the Classification Learner, but the app does not see cell arrays in the workspace. I do understand it's a bad idea to generate dynamic variable names, but what's the solution to my need? Thanks

Melden Sie sich an, um zu kommentieren.

Weitere Antworten (5)

Amit
Amit am 22 Jan. 2014
Bearbeitet: Amit am 22 Jan. 2014
Italo, I am glad you're trying out things on matlab.
Matlab is very good with matrixes. What you're doing in these can be done much easily. For example:
A = 1:3;
B = A.*A; %
You can find many tutorials online on how to use MAtlab. For example: http://www.mathworks.com/academia/student_center/tutorials/launchpad.html
  2 Kommentare
Amit
Amit am 22 Jan. 2014
In you code:
for i=1:3
eval(['A' num2str(i) '= i'])
eval(['B' num2str(i) '= A' num2str(i) '*i']) % Issue was Here. Notice the positions of '
end

Melden Sie sich an, um zu kommentieren.


Gabor
Gabor am 20 Sep. 2021
T=table;
Date=datetime(2014,12,31);
eval(['Dynamic_var_name_' datestr(Date,'mm_dd_yyyy') '=T;']);
This is how you name dynamically a variable or a table or a cell or anything regardless if it is recommended or not.

Jerry Olup
Jerry Olup am 28 Apr. 2018
Bearbeitet: Jerry Olup am 28 Apr. 2018
I did find dynamically named variables useful for a specific need. I have several files in a directory. Each file has a few columns that are read into a structure. It's convenient to read and simultaneously name the variables per a filename. For instance I read to a temp var then use the ill-advised exec capability to assign this to a variable specific to the file I read in. Looping, I read all files in the dir efficiently. 'files' is a cell array of file names discovered in that directory....
tmp = table(dataArray{1:end-1}, 'VariableNames', {'max_mag','max_noise','max_cnt'});
eval([files{i} '=tmp'])
I do see where this is not good for general variable naming, but I believe there's a niche usage in this case. Opinions? Best, Jerry
  3 Kommentare
Jan
Jan am 30 Apr. 2018
Bearbeitet: Stephen23 am 2 Mai 2018
I cannot emphasize it enough how important Stephen's suggestions are. Creating the variables dynamically impedes the JIT acceleration massively, such that the complete function can runs ways slower, not just the line containing these variables. The JIT must be able to handle the case, that one of the "files{i}" is called "plot". Afterwards plot is not a command anymore, but a table object. To catch such problems, all function calls must be checked manually if they have been overwritten dynamically.
Using dynamic field names instead by S.(files{i})=table(...) is safe and efficient. In addition reading the code allows to identify these variables directly: If I find "S.function" in the source code, I know where it is coming from, while for a simple "function" I cannot be sure, if this is a typo or a dynamically created variable. The editor cannot distinguish this also and will assume an illegal definition of a function. Such strange effect can never happen with dynamic field names.
Summary: No, there is no niche for dynamically created variables. eval is a shot in your knee. Sometimes it does not hurt immediately, but the later it starts to bite you, the harder it will be to clean up the code.
This has been discussed exhaustively in the links, Stephen has posted in his answer above. Believe him and the bunch of corresponding threads.
Jerry Olup
Jerry Olup am 12 Aug. 2018
Bearbeitet: Stephen23 am 12 Aug. 2018
Hi Stephen, I'll give the idea of provide parallel constructs where the file-specific variable references are in one cell while data is collected in structure. I've shifted in the last month or so to use python for preprocessing - so this problem has largely gone away and been replaces with xlsread, csvread etc.
>>files data are not restricted to valid field/variable names
My file names are conventionally, ascii with underscores and timestamps yyyymmdd_hhmmss type, so I do see where this is problem. They are pretty specific so I thought I was giving a concrete counter example in contrast to @Italo and @Muna, who started this thread naming generic matrices.
>>you have not given any reason why none of those methods would work.
You're absolutely correct. I latched onto that solution as it was elegant for what I needed.
Thanks for the interaction, best, Jerry

Melden Sie sich an, um zu kommentieren.


César Silva Proaño
César Silva Proaño am 12 Aug. 2018
Hi, look I was doing something similar in order to create a function with the Krammer Method, for solving any size of matrix-equation problem. Look I created a function in order to do this, therefore, I needed to do it automatically, creating variables dinamically. Look at this fucntion.
function [ X ] = funcionMetodoKrammer( A )
%UNTITLED Summary of this function goes here
% Detailed explanation goes here
% ex: A = [-3 2 1 10;5 -8 3 15;-8 -9 10 20];
sizeA = size(A);
sizeFilasA = sizeA(1,1);
sizeColumnasA = sizeA(1,2);
matrizASinResultado = A(1:sizeFilasA,1:sizeFilasA);
matrizResultados = A(:,sizeColumnasA);
if (sizeFilasA == sizeColumnasA - 1)
for (i = 1:sizeColumnasA)
genvarname('matrizColumna', num2str(i));
eval(['matrizColumna' num2str(i) '=A(:,i)']);
end
for (i = 1:sizeFilasA)
genvarname('matrizTemporalColumna', num2str(i));
eval(['matrizTemporalColumna' num2str(i) '=matrizASinResultado(:,i)']);
end
matrizIncognita1 = [matrizResultados,matrizASinResultado(:,2:sizeFilasA)];
for (i = 2:sizeFilasA)
genvarname('matrizIncognita', num2str(i));
eval(['matrizIncognita' num2str(i) '=[matrizASinResultado(:,1:i-
1),matrizResultados,matrizASinResultado(:,i+1:sizeFilasA)]']);
end
else
msgbox('La matriz ingresada para el método Krammer es incorrecta');
end
for (i = 1:sizeFilasA)
genvarname('X', num2str(i));
genvarname('matrizIncognita', num2str(i));
eval(['X' num2str(i) '= det(matrizIncognita' num2str(i) ')/det(matrizASinResultado)']);
end
X = zeros(1,sizeFilasA);
for (i = 1:sizeFilasA)
genvarname('X', num2str(i));
eval(['X' '(1,' num2str(i) ')=X' num2str(i)]);
end
end
%{
Asuminedo que existen variables B1, B2 y B3 se pueden acceder a las
variables de la siguiente manera
B1 = 10; B2 = 11; B3 = 12;
for (i = 1:3)
genvarname('Prueba', num2str(i));
genvarname('B', num2str(i));
eval(['Prueba' num2str(i) '=' 'B' num2str(i) '+10']);
end
%}
I strongly disagree with the idea that you shouldn't use this because, if it exists I mean why not? It is not prohibited, and additionally it is very helpful in some cases.
Regards,
Sebastián
  5 Kommentare
Walter Roberson
Walter Roberson am 13 Aug. 2018
César Silva Proaño:
Imagine that you were building a bird house by using a beer bottle to hammer in nails. You get something made and present it to us as a model for how to make bird houses.
Imagine that we notice that you used the wrong size of nails for the materials, that you used the wrong kind of nails for the materials, that using a beer bottle as a hammer is dangerous, and that our considered experience is that it is a lot better to build bird houses with screws instead of with nails.
In those circumstances, should we advise you to use screws and a screwdriver instead of nails, or should we refrain from saying anything, seeing as you created a birdhouse that looks good enough to you? Should we just shrug our shoulders about the dangers of bottles shattering in hands when used as hammers, figuring that people will eventually figure it out for themselves?
jonas
jonas am 11 Sep. 2018
Bearbeitet: Stephen23 am 20 Sep. 2021
"you just attack this method and you do not present an formal solution"
This is simply untrue. On the contrary, from what I've seen Stephen always provides a concrete solution when possible. Here's an example from 5 minutes ago ( link ) which is nothing out of the ordinary.
"But please make us all a favor and present a code, not just words or links..."
This is the mindset I see in a lot of younger students today - avoid instructions like the plague and feel entitled to a solution. Remember that no one is getting paid to read about your dynamic variables, so you should appreciate any replies including links and words (whatever that means).

Melden Sie sich an, um zu kommentieren.


João
João am 4 Mai 2022
Bearbeitet: João am 4 Mai 2022
I too have a potential reason to want to do what the original OP posted. My example is that I want to numerically solve a system of nonlinear functions, in which the number of functions and variables depend on the input. I don't think any of the suggested alternatives solve this case. Am I wrong?
  14 Kommentare
Stephen23
Stephen23 am 5 Mai 2022
Bearbeitet: Stephen23 am 6 Mai 2022
"So having to define functions for all increments and all possibilities is not feasible."
Sure.
"I want to use a loop to define the equations for each set of objects at rest and in motion, and skip having to write them one by one"
So presumably there is some kind of pattern to these things: those equations must be abe to be defined systematically depending on the number of objects/whatever (otherwise your task is moot), and that is really what you need to utilize if you want a general solution to this (regardless of Python or MATLAB).
Please show one (or all) of the equations for three objects, to give me an idea of how they change.
"Over time some objects which were at rest become affected by the pressure wave, so no longer in equilibrium, so the equations of motion will change over time as the net force also changes"
That sounds like something that could be handled using indexing. Or at worst some loops and IFs.
The more you explain, the more your approach that "the name of variables depend on the range of the loop" seems ... unhelpful in either language. Numpy and MATLAB both work with arrays, so should you.
João
João am 6 Mai 2022
@Stephen23 Yes, equations must be abe to be defined systematically depending on the number of objects. And yes, for each time increment I know which equations to use and which x, y, z, ... to define.
For two objects I would have something like:
x, y, z, j = vars # variables
eq1 = (m*g - k*(y - x)) * dt - m * (j - c) # where m, k, g and c are known values
eq2 = (k*(y - x) + m*g - k*x * dt - m * (z - d) # where m, k, g and d are known values
eq3 = m * (c + d) - m * (z + j)
eq4 = m*g*y - 1/2*k*(y-x)**2 + m*g*x - 1/2*k*(x-l)**2 + m*g*l - 1/2*k*(l)**2
- 1/2*m*(j**2 - c**2) - 1/2*m*(z**2 - d**2)
For three objects I would have something like:
x, y, z, j, l, f = vars # variables
eq1 = (m*g - k*(y - x)) * dt - m * (j - c) # where m, k, g and c are known values
eq2 = (k*(y - x) + m*g - k*(x - l) * dt - m * (z - d) # where m, k, g and d are known values
eq3 = (k*(x - l) + m*g - k*l) * dt - m * (f - e) # where m, k, g and e are known values
eq4 = m * (c + d + e) - m * (z + j + f)
eq5 = m*g*y - 1/2*k*(y-x)**2 + m*g*x - 1/2*k*(x-l)**2 + m*g*l - 1/2*k*(l)**2
- 1/2*m*(j**2 - c**2) - 1/2*m*(z**2 - d**2) - 1/2*m*(f**2 - e**2)
eq6 = j - c # assuming that the velocities of object 1 and object 2 are the same during impact, i.e. when object 1 hits objects 2 they have the same velocity
So this made me realise I have to keep making assumptions as the number of objects grows.
So I need to solve the equations explicitly by Runge-Kutta or Central Difference methods...
I need to restructure my code. Thank you for the constructive input!

Melden Sie sich an, um zu kommentieren.

Kategorien

Mehr zu Loops and Conditional Statements 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!

Translated by