Is it possible to evaluate a colon notation string without using the eval function?

In my pursuit of always trying to eliminate the use of the eval function in my code (whether it makes sense to do this or not), I am looking for a way to turn a string such as mystring = '[1:10]'; into the column vector myvector = [1 2 3 ... 10]; without using the eval function.
mystring could be '[1:10]', '[1:1:10]', '[2:2:140 146:2:260 123435]', or just about anything the user puts in there that will evaluate to a vector at the matlab command prompt.
The usage comes from reading a kind of input spreadsheet which contains a colon notation string for each row into matlab, and having matlab create the corresponding vectors. Currently this is done easily for each row with myvector = eval(mystring);. I can't think of a better way to do it... maybe it doesn't exist, but I'm all ears if anybody has some ideas.
I know there is a way to go the other way on the file exchange (vect2colon.m, by Javier Lopez-Calderon). Realistically, the biggest performance hit comes from reading the spreadsheet into Matlab rather than using the eval function, but I'm still curious about this question.

1 commentaire

Stephen23
Stephen23 le 26 Sep 2018
Modifié(e) : Stephen23 le 22 Jan 2019
This is easy to achieve efficiently without eval (either explicitly called or inside str2num). See my answer to this question:

Connectez-vous pour commenter.

 Réponse acceptée

If you’re doing simple numeric conversions (the strings are always arrays such as you’ve illustrated), str2num is an option to avoid eval:
a = '[1:10]';
an = str2num(a)
ca = class(an)
an =
1 2 3 4 5 6 7 8 9 10
ca =
double
The ‘ca’ assignment isn’t required for the code, it’s there simply to demonstrate that the result is the double array I assume you want.

5 commentaires

Nice, I knew there was a simple answer I was glossing over. Thanks
Please take a look inside the str2num.m file and check, if it does not call eval by itself.
@Jan: I checked and str2num does indeed call eval within a subfunction called protected_conversion :( ... bummer.
@Ryan: Ah, no problem. If the subroutine's name contains the string "protected" nothing can happen. ;-)
But as far as I remember str2num checks the string exhaustively before delivering it to eval, such that a 'system(''format C:'')' will be rejected. Will you dare to test this?

Connectez-vous pour commenter.

Plus de réponses (1)

You can use scanf():
mystring = '[1:10]';
numbers = sscanf(mystring(2:end-1), '%d:%d') % [1,10]
numbers10 = numbers(1):numbers(2) % [1,2,3,4,5,6,7,8,9,10]
% Now turn the 1:10 into 1:100
% in case you really wanted that and it was not a typo.
numbers100 = linspace(numbers(1), 10*numbers(2), 100)
Funny I never have to look for a way to eliminate the use of eval in my code like you because it never goes in there in the first place. I never use it and it never occurs to me that I would even use it at all. It's not in my mindset. I've never had to use it in any of my programs.

6 commentaires

Image Analyst 1: Thanks for you quick response. Going to 100 was indeed a typo, that I have now fixed. And I should have been a little more clear in my description as well (I have now clarified the question). I used 1:10 as a simple example. Realistically the string might be '[1:10]' or '[1:1:10]' or '[2:2:140 146:2:260 123435]' or really anything a user wants, depending on the circumstances. All of these situations are things that eval would handle without hiccup or any additional coding. I think sscanf would need to know something about the format, or at least I would need to write a function to handle every case, similar to vect2colon.m available on the file exchange, but in the other direction.
I'm with you on the use of the eval function... but I'm also maintaining a huge number of codes where other people have made liberal use of eval calls in hundreds of different scripts and functions that are all intertwined and have been in use for decades, so it takes a lot of time to remove every call to eval. This is part of my effort to remove these calls throughout the codes, slowly but surely. However, I think this might be one exception for which the eval might be suitable vs. the alternative. Not sure. Thanks!
Stephen23
Stephen23 le 30 Juin 2015
Modifié(e) : Stephen23 le 26 Sep 2018
"...this might be one exception for which the eval might be suitable..."
This is begging the question: "when executable strings encode numbers, executing them is the best way to get the numbers". But why does this need arise in the first place? When numeric data is encoded in the form of executable strings then of course some slow and non-robust parsing is going to be required... but most likely there would be a much more robust and probably conceptually neater way of doing this anyway, without using those strings at all.
Ryan, I tested Star's solution with your '[2:2:140 146:2:260 123435]' and it works fine, so I'm not seeing how eval() would be a preferable way to accomplish this task. For the cases you gave, this is not an exception like you suggested.
Agree with Stephen, why are you getting strings like this? Is it user input? If so, rather than an executable string how about three inputs: Lower_end, stride, upper end?
Yes Star's solution works fine... it's just that as Jan pointed out, the str2num function ultimately calls the eval function to do it's business, so it would not be any more efficient than just using the eval function in the first place. Sean & Stephen, I get your point. The need for this arises solely out of user convenience and a long history of doing it this way. It is of course possible to leave numbers as numbers, but the matlab colon notation is a convenient shorthand to creating a list of integers that might happen at regular intervals, skip a group, then continue in a similar patter (such as '[2:2:120 126:2:130]'). This sort of thing comes into play when removing outliers from a dataset, or similar kind of data selection. Ultimately, I think I will just leave the code as is even though it hurts my brain to see eval functions laying around in the code.
MathWorks should sell "I used eval" shot glasses to help with the brain hurt :)

Connectez-vous pour commenter.

Catégories

En savoir plus sur Variables dans Centre d'aide et File Exchange

Produits

Community Treasure Hunt

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

Start Hunting!

Translated by