Alternative to Eval for small number of variables
이전 댓글 표시
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
"but I want to do this in a way that doesn't use eval."
Nothing in your task seems to require EVAL: why not just use ISMEMBER or STRCMPI or similar to get the index and use that?
Note that your code design would proabably be simpler and more expandable if you replaced all of those separate numbered variabels with one vector. Having lots of numbered variable names is a sign that you are doing something wrong: remember that meta-data (e.g. pseudo-indices) is data, and data belongs in variables (and not in variable names).
HpW
2022년 9월 25일
"The issue I have is that I dont know what variable names are going to be in the .csv file ahead of time"
No, that is not the issue. The problem is caused by the poor data design of your code.
"So I don't see how I can use strmp() or ismember() without coding all possibilities."
By designing your code to use lots of separate variables, you have painted yourself into a corner: you can only access that data by using slow, complex, inefficient approaches (like EVAL). Your code design forces you to do that.
However if instead you had designed your code better by using vectors/matrices/arrays, then this task would be simple and efficient to resolve (i.e. using ISMEMBER etc. as recomended), regardless of what the files contain.
The files are not the problem, this is:
a = 10;
b = 15;
c = 1;
d = 20;
e = 25;
Put those value into a vector... and suddenly this problem is easy to solve. Just as it should be.
HpW
2022년 9월 25일
채택된 답변
추가 답변 (2개)
Jeff Miller
2022년 9월 25일
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
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
HpW
2022년 9월 28일
"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.
카테고리
도움말 센터 및 File Exchange에서 Structures에 대해 자세히 알아보기
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!