How do I create a new variable with another variables' value as its name?

I need to go through multiple text files and create arrays based on the data in them. However, each variable needs to have it's own name based on the file it's from. So far I've gotten this:
%code to import multiple files at once
files = dir("*.csv");
len = length(files);
for i = 1:len
array_name = sprintf("t%s",files(i).name); %generates the proper file name for array
new_arr = readmatrix(files(i).name, 'Range', 'A3:A25'); %import data from file
%rename new_arr to array_name string here
end
The issue is that each time the function loops, I need the arrays created to take on the array_name value as its variable name (i.e. "new_arr" should be replaced with the value of array_name).
I am aware that dynamic variables are not best practice, but I do need to create a new variable each time. I have tried eval, but it will not accept the string output of array_name and I cannot use struct because the string as a field name appears to be invalid.

5 commentaires

Why would you need to create such a thing? Even if you do, you'll have the exact same problem every single time you try to use the variable.
I have to use the variables simutaneously, so I need the data to import into a new variable without losing the old information. They need to be named with the speficied convention so that I can identify the information properly.
"I have to use the variables simutaneously, so I need the data to import into a new variable without losing the old information."
Well, that could be easily achieved using the simple, standard, efficient approach of one array and indexing. For example:
S = dir("*.csv");
for k = 1:numel(S)
S(k).data = readmatrix(S(k).name, 'Range','A3:A25');
end
Look at that: neater, simpler, faster code that actually works. You're welcome! In contrast your approach is slow, complex, inefficient, liable to bugs, harder to debug, and currently does not work.
"They need to be named with the speficied convention so that I can identify the information properly."
So you want to keep some meta-data. Well, keeping meta-data is easy, and it certainly does not require magical variable names. In fact, your approach would be about the worst way to store meta-data, because you are forcing yourself into writing fragile, complex, inefficient code just to perform the basic task of accessing your data. The meta-data gets in the way!:
"I am aware that dynamic variables are not best practice, but I do need to create a new variable each time."
The curious thing is that every time a user writes that they "need" to do this, they inevitably omit to actually explain how this data will be processed. Every time I ask this, no answer. So, if you would be so kind, please explain your very special data-processing such that you "need" to do this. I would be very interested to know how you will process this data, so that I can learn about the motivation for such an approach. It would help me to understand the situation better.
So far it just seems to be a classic example of:
You are presupposing a particular (buggy, anti-patten) solution instead of asking about your actual task.
My goal from the beginning was to create new arrays with proper variable names.
I got handed many files from which I had to create multiple variables to use in another program. I was trying to expedite the process of making each variable by sticking it in a loop instead of doing it by hand, hence the need for dynamic variables. I need the naming convention to match, because I would not be able to find the right arrays otherwise - in the second program, I can only access the data through visual inspection of variable names.
I appreciate the advice you've given, hopefully I can find a better solution in the future without using dynamic variables - for now I just had a greater need to make the new variables.
Stephen23
Stephen23 le 9 Fév 2023
Modifié(e) : Stephen23 le 9 Fév 2023
"in the second program, I can only access the data through visual inspection of variable names"
My heartfelt sympathy on having to work with such a tool. Hopefully you can see where things could be done better, should you ever need to implement something like that youself. Good luck!
You will need to keep in mind that naming variables after filenames is very fragile: many/most characters that are valid in filenames are not valid in MATLAB variable names, so in general you would need to convert/remove such characters to something valid. This then causes collisions, where different filenames convert to the same variable name... you can fiddle around with tools like GENVARNAME(), but ultimately there is no trivial solution to this.

Connectez-vous pour commenter.

 Réponse acceptée

Dinesh
Dinesh le 9 Fév 2023
Modifié(e) : Dinesh le 9 Fév 2023
Hi Nithila,
I believe that the mistake is because of incorrect usage of "eval". The following code worked for me when I was trying to use "eval" in your case:
files = dir("*.csv");
len = length(files);
for i = 1:len
array_name = sprintf('t%s',files(i).name);
eval([array_name '= readmatrix(files(i).name, "Range", "A3:A25");']);
end
disp(tbos2021ModC); % displaying the dynamically created variable name ("t<file_name>") through a file in my local directory
Output:
As you can see, the variable that was dynamically created has the required data stored in it.

3 commentaires

I tried using it with the same syntax, but I am getting this error:
Error using eval
Argument must be a text scalar.
Error in script (line 26)
eval([array_name '= readmatrix(files(i).name, "Range", "A3:A2500007");']);
Make sure you use single quotes for t%s within the sprintf function to solve the error.
array_name = sprintf('t%s',files(i).name);
Note that you are not stripping off the file extension .csv when you do the dynamic assignment, so you are going to end up assigning to a field named csv in the target variable.

Connectez-vous pour commenter.

Plus de réponses (1)

There are very few places in MATLAB that require a bare variable name with no possibility of any kind of indexing. The ones that I can come up with at the moment are:
  • for and parfor loop index variable name
  • names of functions in function definitions
  • names of input and output variables in function definitions
  • name of exception object in catch statement
  • parameter names in parameter validation blocks
  • names of variables to save in save() calls, and names of variables to load in load() calls
If you need to generate any of those dynamically (other than load/save) then you are quite likely Doing The Wrong Thing. (there are workarounds for load/save)
If you are not doing any of the above, then you do not need to generate top-level variable names dynamically.
You can create cell arrays of content and have a corresponding name array. Or you can generate dynamic field names for a struct. Or you can define dynamic property names for objects.

2 commentaires

If by "bare variable name" you're referring to an identifier that passes the isvarname test I'd add struct array field names to your list. You can't have a field named "abc+123" or "d(2)" for example.
You also can't use indexing when defining a global or persistent variable. You can't, for example, make the second element of an array d global with global d(2) while leaving the rest of d non-global.
global and persistent are good additions to the list.
Fieldnames needing to be plain identifiers is important only in the context of setfield and getfield
That is, it is completely legal to have code such as
body.ankles{2} = 'itchy'
but it is not legal to have code such as
for body.ankles{2} = 1:5
The case of
try
#deliberate error
catch body.ankles{2}
disp(body.ankles)
end
turned out to be an interesting one. The form is not a syntax error -- but if the token immediate after catch is not a bare variable name, then MATLAB treats the situation as-if no name had been given for the exception, with the expression being treated as the first executable statement in the catch block, as if you had written
try
#deliberate error
catch
body.ankles{2}
disp(body.ankles)
end

Connectez-vous pour commenter.

Catégories

Community Treasure Hunt

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

Start Hunting!

Translated by