Alternative to Eval for small number of variables
7 visualizaciones (últimos 30 días)
Mostrar comentarios más antiguos
HpW
el 25 de Sept. de 2022
Hello
I have been reading about using (or not using) eval, but have a situation where I cannot figure out how to get around it. I am hoping that someone can help me.
I have a program that checks some values based on an external .csv file.
I have variables already set that are associated with a value, eg
var1 = 50
var2 = 500
...
The .csv file lists the variable names in col 1, and has the numeric value to check in col 2 -
{'var1'} {[val1]}
{'var2'} {[val2]}
{'var3'} {[val3]}
... .....
{'varN'} {[valN]}
The specific var names and values may change value and order, so the .csv file could look like this:
{'var3'} {[val3]}
{'var2'} {[val2]}
{'var1'} {[val1]}
... .....
{'varN'} {[valN]}
I am reading in the file using readcell:
F = readcell('filename.csv');
var_names = F(:,1);
var_values = cell2mat(F(:,2));
As noted, the order of entries into the .csv file may change, so I can't code something like:
if var1 > var_values(1)
% something
end
because sometimes var2 and its associated value may be in the first row etc, or var1 might be in row 3 etc
I get what I want using
for i = 1:length(var_names)
if eval(var_names{i}) > var_values(i)
% something
end
end
but I want to do this in a way that doesn't use eval. Any help would be appreciated.
thanks!
------------------------------------------------------------------------
ADDENDUM:
I have attached a csv file as suggested.
F = readcell('filename.csv');
var_names = F(:,1)
var_values = cell2mat(F(:,2))
a = 10;
b = 15;
c = 1;
d = 20;
e = 25;
To attempt to clarify: The issue I have is that I dont know what variable names are going to be in the .csv file ahead of time. So I don't think I can use ismember() or strcmp()
Lets say I want to check if the variable listed in the first column of the csv file (var_names) has a value assigned that is > than the value in the csv column 2 (var_values). However, I don't know before hand which of the possible variables will be in the csv file. So I don't see how I can use strmp() or ismember() without coding all possibilities.
So for example lets say that the first line in the csv file is 'a' and '5' (as it is in the attached file). I therefore want to check that workspace variable a (which was assigned a value of 10 above) is > 5 (value in the csv corresponding to the row with var_name = 'a') and store the answer (1 or 0) in variable N:
I could do it using eval:
for i = 1:length(var_names);
N = eval(var_names{i}) > var_values(i)
end
or as suggested using strcmp:
for i = 1:length(var_names);
if strcmp(var_names{i}, 'a')
N = a > var_values(i)
end
end
for i = 1:length(var_names);
if strcmp(var_names{i}, 'b')
N = b > var_values(i)
end
end
for i = 1:length(var_names);
if strcmp(var_names{i}, 'c')
N = c > var_values(i)
end
end
etc etc
but the issue is that maybe the csv file only contains a few out of many posisble variables.....I wanted to avoid having to code all possibilities. Even if I put the varaibles names in a vector I still seem to run into the same issue when assigning a value to N.
Thanks again!
5 comentarios
Stephen23
el 25 de Sept. de 2022
Editada: Stephen23
el 25 de Sept. de 2022
"so lets say I put those variables in a single vector:"
As they should be.
"I still am not following how I can accomplish the task in this way either?"
ISMEMBER (hint: look at all of its outputs). You probably don't even need a loop.
Respuesta aceptada
Image Analyst
el 25 de Sept. de 2022
You forgot to attach your data. If it's secret, just mock up some dummy data.
Try strcmpi(), contains(), or ismember()
if strcmpi(var_names{i}, 'var1') && (var_values(i) > var_values(1))
% Do something
end
If you have any more questions, then attach your data and code to read it in with the paperclip icon after you read this:
4 comentarios
Stephen23
el 1 de Oct. de 2022
Editada: Stephen23
el 1 de Oct. de 2022
"Is there a way to pull the values from the workspace into some structure automatically?"
Of course: by using EVAL (or equivalents).
But given that the title of your question is "Alternative to Eval for small number of variables", then you have not really gained anything at all, just performed the same operation in a more complex way.
"I would need a way to get the values from the workspace automatically."
The problem then is the data design.
How did you get all of those variables into the workspace in the first place?
Más respuestas (2)
Jeff Miller
el 25 de Sept. de 2022
Put your workspace variables in a struct and then use var_names to access the fields of that struct, something like this:
wrkstruc.a = 5;
if wrkstruc.(var_names{1}) > var_values(1)
% do something
end
Stephen23
el 26 de Sept. de 2022
Editada: Stephen23
el 26 de Sept. de 2022
Approaches like EVAL and structure fields for this task are far too complex.
You need to learn how to use arrays to write simple and efficient code, not fight MATLAB with complex data design.
Note that I changed the order of the rows in the CSV file, because providing that data in exactly the order a,b,c,d does not really make demonstrating or testing the soluton very... comprehensive. Non-trivial example data make the solution easier to illustrate.
T = readtable('filename.csv')
V = [ 10; 15; 1; 20; 25];
C = ["a";"b";"c";"d";"e"];
[X,Y] = ismember(C,T.Var1); % MATLAB is so easy when you use arrays...
N = V(X) > T.Var2(Y(X)) % ... because then you can write simple and efficient code.
Displaying the results (just for interest, not part of the solution):
compose("%s: %d",C(X),N)
Summary: use MATLAB arrays to write simple and efficient code. Your approach of forcing meta-data into variabe names (and using structure fields, etc) is far too complex for such a simple task. In case the message is not clear yet, you need to learn to use arrays to use MATLAB efficiently.
2 comentarios
Stephen23
el 1 de Oct. de 2022
Editada: Stephen23
el 1 de Oct. de 2022
"The issue in my specific case is that the specific variable names in C may change over time and was looking for a way to future proof the code in case in the future someone wants to look at variable 'f'"
That point does not make much sense to me: you will need to have the values defined before you can use them, so either they will need to be defined in some arrays (leading to simple and efficient MATLAB code) or they will need to be defined as lots of separate variables (your preferred approach, leading to slow, complex, inefficient, insecure, buggy code that is hard to debug).... but in either case, the values will need to be defined before you can use them.
"I have been reading about using (or not using) eval, but have a situation where I cannot figure out how to get around it."
The requirements you have given so far are contradictory: you want to access lots of variables by name without accessing variables by name (using EVAL et al). It should be clear that there is no solution to this.
The best approach by far would be to reconsider your data design.
Ver también
Categorías
Más información sobre Matrix Indexing en Help Center y File Exchange.
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!