Put variable names into a cell array or string array

I have a number of similarly named variables in my script, eg
VarableAB
VarableDEF
VarableGHIJK
:
VarableZ
How can I get all these variable names into a cell array or a string array that I can loop round to do the same thing to each variable?

7 Comments

"I have a number of similarly named variables in my script..."
And that is the cause of your troubles. Solution: better data design.
The variables are not named dynamically. They are struct variables for 15 different sets of data. I did it this way so that I can select one and pass it to a function for plotting or analysis. The names were carefully chosen so that I could easly extract subsets by searching for substrings. (Maybe I should have given the real names instead of those made-up ones.)
Only now have I the need to do the same analysis on all 15 structures. I could easily cut and paste 15 function calls, but that approach is prone to errors and using a loop seemed better.
They aren't named with sequentially numbered names like x1, x2, x3, etc. but they are dynamic; they're not fixed when the code is written.
How did you create these variables? If you called load to bring them into the workspace, call it with an output argument so that all those struct arrays become fields in one variable whose name you know and have fixed when you wrote the code.
clear all
whos -file census.mat
Name Size Bytes Class Attributes cdate 21x1 168 double pop 21x1 168 double
data = load('census.mat') % variables in MAT-file become fields in struct
data = struct with fields:
cdate: [21x1 double] pop: [21x1 double]
No matter what variables happen to be in census.mat, I can access them as fields of data. Dynamic field names aren't as problematic as dynamic variable names are.
fn = fieldnames(data)
fn = 2x1 cell array
{'cdate'} {'pop' }
x = data.(fn{1}) % the values from the variable cdate in census.mat
x = 21×1
1790 1800 1810 1820 1830 1840 1850 1860 1870 1880
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
Note that I know exactly what variables will be in the workspace when those five lines of code are executed: data, fn, and x.
whos
Name Size Bytes Class Attributes data 1x1 616 struct fn 2x1 256 cell x 21x1 168 double
What if census.mat had had variables named plot, min, max, quit, etc.? Would you expect MATLAB to access those variables or the functions with whom they share names?
"I did it this way so that I can select one and pass it to a function for plotting or analysis."
Convenience for humans is only sometimes convenient for computer processing.
"The names were carefully chosen so that I could easly extract subsets by searching for substrings. (Maybe I should have given the real names instead of those made-up ones.)"
Variable names are not text, they cannot be searched for substrings.
If you had designed your data better (by storing that meta-data as data in its own right) then your task would be easy.
"Only now have I the need to do the same analysis on all 15 structures."
Yet you really painted yourself into corner with that bad data design. Solution: do not have 15 separate structures.
"I could easily cut and paste 15 function calls, but that approach is prone to errors and using a loop seemed better."
Loops are much better. Simple, robust, and efficient loops use indexing. To use indexing you need to have one array (not 15 separate structures). In your case, consider using a structure array and storing that meta-data (which is data after all) in its own field. Then you can easily do as much substring matching as you require (e.g. using comma-separated lists) and your code will be simple and neat and expandable and robust and efficient.
I feel put-upon by this thread.
I am not a programmer, just a scientist who tries to use MATLAB to analyse data. Maybe I did paint myself into a corner with this problem, but I didn't know any better. I struggle with many concepts in MATLAB and other programming languages and don't feel that I have the time to learn them properly. Muddle through, that's my way.
Thanks for all the comments. I know you meant well.
"I am not a programmer, just a scientist who tries to use MATLAB to analyse data."
Me too.
"Maybe I did paint myself into a corner with this problem, but I didn't know any better."
We all start new topics knowing nothing about them.
"I struggle with many concepts in MATLAB and other programming languages and don't feel that I have the time to learn them properly."
Using vectors, matrices, arrays and indexing are not esoteric things that only programmers understand, they are really very fundamental to using MATLAB:

Sign in to comment.

 Accepted Answer

Adding to the comments: you are putting data (a description and therefore a property) in the variable name. That is where your design is going wrong.
What you should probably have done is to write each of them to a separate mat file, or make them all fields of a struct.
When you have a bunch of mat files you can use dir to generate the array to loop over. If you choose to make it a struct array you can use fieldnames like this:
Varable.AB=1;
Varable.DEF=2;
Varable.GHIJK=3;
for fn=fieldnames(Varable).'
current = Varable.(fn{1});
fprintf('value of field %s is %d\n',fn{1},current)
end
value of field AB is 1 value of field DEF is 2 value of field GHIJK is 3

1 Comment

Supplementing this answer: using a structure array and storing that meta-data in its own field also allows the use of meta-data which are not valid fieldnames:
S(1).data = 11;
S(1).meta = 'AB';
S(2).data = 23;
S(2).meta = 'CDE';
S(3).data = 99;
S(3).meta = 'This is not a valid fieldname';
for k = 1:numel(S)
fprintf('The value of element %d is %d and has text "%s"\n',k,S(k).data,S(k).meta);
end
The value of element 1 is 11 and has text "AB" The value of element 2 is 23 and has text "CDE" The value of element 3 is 99 and has text "This is not a valid fieldname"
and makes it easy to obtain data based on substrings on the meta-data:
iwant = 'valid'; % some substring
idx = contains({S.meta},iwant);
S(idx).data
ans = 99
Although rather than matching substrings you might as well store each meta-data value in its own field:
In short: better data design make your code more robust (as well as neater, more efficient, etc.).

Sign in to comment.

More Answers (1)

I found I way to do what I want. Is this so bad?
S = whos( '-regexp', '^Varable' );
varables = extractfield( S, 'name' );
for i = 1:size(varables,2)
varable = char(varables(i));
myFunction( eval( varable ) );
end

1 Comment

"Is this so bad?"
From the MATLAB documentation: "A frequent use of the eval function is to create sets of variables such as A1, A2, ..., An, but this approach does not use the array processing power of MATLAB and is not recommended. The preferred method is to store related data in a single array. If the data sets are of different types or sizes, use a structure or cell array."

Sign in to comment.

Categories

Products

Release

R2024b

Asked:

on 9 Oct 2024

Edited:

on 1 Dec 2024

Community Treasure Hunt

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

Start Hunting!