Alternative to Eval for small number of variables

조회 수: 11 (최근 30일)
HpW
HpW 2022년 9월 25일
편집: Stephen23 2022년 10월 1일
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_names = 4×1 cell array
{'a'} {'b'} {'c'} {'d'}
var_values = cell2mat(F(:,2))
var_values = 4×1
5 10 15 20
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
N = logical
1
N = logical
1
N = logical
0
N = logical
0
or as suggested using strcmp:
for i = 1:length(var_names);
if strcmp(var_names{i}, 'a')
N = a > var_values(i)
end
end
N = logical
1
for i = 1:length(var_names);
if strcmp(var_names{i}, 'b')
N = b > var_values(i)
end
end
N = logical
1
for i = 1:length(var_names);
if strcmp(var_names{i}, 'c')
N = c > var_values(i)
end
end
N = logical
0
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
HpW
HpW 2022년 9월 25일
Hi
so lets say I put those variables in a single vector:
v = [10 15 1 20 25];
I still am not following how I can accomplish the task in this way either?
could u explain further?
thanks
Stephen23
Stephen23 2022년 9월 25일
편집: Stephen23 2022년 9월 25일
"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.

댓글을 달려면 로그인하십시오.

채택된 답변

Image Analyst
Image Analyst 2022년 9월 25일
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
HpW
HpW 2022년 9월 28일
Thanks. This was very helpful. Is there a way to pull the values from the workspace into some structure automatically? If so I could deal with the fact that I only care about the variables listed in the csv file by doing something like this I think:
vars = whos
varNames = {vars.name}
S = struct;
for i = 1:length(var_names) % variables names from csv file
for j = 1:length(varNames) % variables names from workspace
if strcmp(varNames{j}, var_names{i})
S.varNames{j} = %value of variable varNames{j} - but dont know how to do this...
end
end
This would give me a structure S with only the variables/values from the csv file, but the transformation from a string variable name to the actual variable name seems to still be an issue, eg, I would need a way to get the values from the workspace automatically. If it helps, the values are all going to be doubles, nothing more complex than that.
Stephen23
Stephen23 2022년 10월 1일
편집: Stephen23 2022년 10월 1일
"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?

댓글을 달려면 로그인하십시오.

추가 답변 (2개)

Jeff Miller
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
  댓글 수: 1
HpW
HpW 2022년 9월 28일
Thanks. This does work assuming that I prepopulate the structure with the values from the workspace. Ideally I am looking for a way to do this without necessarily knowing the variables which will be listed in the csv file ahead of time. The workspace variables may change over time.

댓글을 달려면 로그인하십시오.


Stephen23
Stephen23 2022년 9월 26일
편집: Stephen23 2022년 9월 26일
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')
T = 4×2 table
Var1 Var2 _____ ____ {'a'} 5 {'c'} 15 {'b'} 10 {'d'} 20
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.
N = 4×1 logical array
1 1 0 0
Displaying the results (just for interest, not part of the solution):
compose("%s: %d",C(X),N)
ans = 4×1 string array
"a: 1" "b: 1" "c: 0" "d: 0"
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
HpW 2022년 9월 28일
Thanks. Your points are well taken. This does work assuming I have arrays V and C set ahead of time. 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'
Stephen23
Stephen23 2022년 10월 1일
편집: Stephen23 2022년 10월 1일
"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.

댓글을 달려면 로그인하십시오.

카테고리

Help CenterFile Exchange에서 Matrix Indexing에 대해 자세히 알아보기

태그

제품


릴리스

R2020b

Community Treasure Hunt

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

Start Hunting!

Translated by