MakaPakaTobyHannah Posted April 14, 2019 Report Share Posted April 14, 2019 A text string array can contain items consisting only of letters, or of letters and digits, or of digits only. Example: 33e re 33e r BARLINE 33e 30q 8ts[[ 9ts 8]] BARLINE 6[ 8 30[ 33]] BARLINE 31[ 9] rq BARLINE 34e re 34e r BARLINE 34e 31q 9ts[[ 30ts 9]] BARLINE Stepping through each text item of this array for evaluation is not the issue. The question is: How can I quickly ascertain if an element contains number(s) only? Or whether an element contains letters only (i.e. no special characters, such as "[" ). Quote Link to comment Share on other sites More sharing options...
Cory Posted April 14, 2019 Report Share Posted April 14, 2019 You could try to cast to an integer for the numeric check. But that seems inelegant. If it were me, I'd write a sub-macro that evaluates each character and returns a value representing the type that you can use to control your logic. Quote Link to comment Share on other sites More sharing options...
MakaPakaTobyHannah Posted April 14, 2019 Author Report Share Posted April 14, 2019 Hm... how would I evaluate each character and get it to return a value representing the type? It seems like this shouldn’t be hard. I discovered that if I convert a string to an integer, for instance: "1cd" the integer returns "1", i.e. stripping out the letters. I could then check if the integer variable equals the text variable - where that is the case, I know that the text item contains only numbers... As I am typing this it makes me wonder... as converting "1cd" to an integer yields "1" I then know that the string does not contain only digits. That’s fine as far as it goes. But it wouldn’t tell me, for instance, if the text string contains only letters. For instance, converting "0abc" and "abc" to an integer yields "0" in both cases. But one text string contains only letters, the other one also contains a zero. Quote Link to comment Share on other sites More sharing options...
rberq Posted April 14, 2019 Report Share Posted April 14, 2019 I can't think of a way to do it without checking every character. It shouldn't be necessary to compare every character to A, then to B, then to C, and so on -- you can reduce the number of IF statements involved by looking for ranges. For example, Variable modify entire string to uppercase Repeat for each character If character >= A and If character <= Z ... ... If character >= 0 and If character <= 9 ... ... Repeat end Quote Link to comment Share on other sites More sharing options...
kunkel321 Posted April 15, 2019 Report Share Posted April 15, 2019 Regarding checking for letters: I see that you can change a string from lower- to upper-case and vise versa. You could save copies of the sting, to var1 and var2, then make var1 UPPER and var2 lower and compare the two using the 'case-sensitive' option. If they're the same--no letters. ...wouldn't detect numbers or special characters though... Quote Link to comment Share on other sites More sharing options...
MakaPakaTobyHannah Posted April 15, 2019 Author Report Share Posted April 15, 2019 I was afraid there wouldn’t be a straightforward approach. Thanks for the tips. For now, I have coded as follows: The string variable I need to check is %pitchesAndRests[%counterPlusOne%]%. I convert it to an integer and then compare the integer to the string. If they are identical, then I know that the string item consists of digits only. Conversely, if they were not identical, I would know that there are other characters, but I would not know if there is a mixture of numbers and letters. I know I could solve this in an "annoying" way... was just hopeful that some of the brilliant people here might have an ingenious solution that I can’t see... Thanks again, everyone! Quote Link to comment Share on other sites More sharing options...
acantor Posted April 15, 2019 Report Share Posted April 15, 2019 Here is a way to check if a text string contains numbers. It tests whether the text string contains a zero, then a one, then a two... all the way to nine. Variable Set String %x%: Prompt Variable Set Integer %Digit% to 0 Repeat Until %Digit% Equals "9" If Variable %x% Contains "%Digit%" Text Box Display: "%x%" contains numbers Macro Stop End If Variable Modify Integer %Digit%: Increment End Repeat Text Box Display: "%x%" does NOT contains numbers Quote Link to comment Share on other sites More sharing options...
rberq Posted April 15, 2019 Report Share Posted April 15, 2019 4 hours ago, MakaPakaTobyHannah said: convert it to an integer and then compare the integer to the string. If they are identical, then I know that the string item consists of digits only For that to work, I think there is a limit to the size of the integer. For example, the lines below always return "01234567899" in the Text Box Display, once the Set String exceeds 10 digits. Comparing the string to the integer would not result in an equal condition. Variable Set String %T1% "0123456789987654321001234567899876543210012345678998765432100123456789987654321001234567899876543210" Variable Modify String: Convert %T1% to integer %N1% Text Box Display: %N1% I think your best bet is the "annoying way" that Cory originally suggested. if the ONLY special characters that can be there are "[" and "]", the job is simpler. If ME had commands for inclusive OR, exclusive OR, and AND, for string variables of different lengths, it would also be simpler. But it's an interesting question. I will keep trying to think of an ingenious solution. 🙂 Quote Link to comment Share on other sites More sharing options...
acantor Posted April 15, 2019 Report Share Posted April 15, 2019 I just tested my script with lengthy strings. It fails when the string is too long. But 500 characters seems to be OK. Quote Link to comment Share on other sites More sharing options...
rberq Posted April 15, 2019 Report Share Posted April 15, 2019 2 hours ago, acantor said: I just tested my script with lengthy strings. It fails when the string is too long. But 500 characters seems to be OK. It's odd your script would fail with long strings. I tested it with a string over 400,000 bytes long, with digits near the very end. (Though I ddin't use a Repeat loop, just hard-coded multiple IF CONTAINS statements.) It took awhile to run, but worked fine. Timeout of some sort, maybe? Quote Link to comment Share on other sites More sharing options...
MakaPakaTobyHannah Posted April 15, 2019 Author Report Share Posted April 15, 2019 7 hours ago, rberq said: For that to work, I think there is a limit to the size of the integer. That’s interesting to know; I will keep that in mind. Here, it’s a non issue, as there won’t be any strings containing more than two digits (by the way, this is music input code manipulation...) acantor’s looping script may well be the most efficacious way of getting the information I need with respect to checking for the presence of digits. A positive result, however, only reveals that digits are present; it does not indicate whether there are digits only, or a mixture of digits and letters. I need to perform manipulations on those items of the array that contain only digits. I really appreciate the constructive feedback! rberg, if that "ingenious solution" should pop into your head... I’ll be happy to find out about it. I dreamed of a solution to my code the other night. When I awoke, that solution was not re-constructible... 😉 Too bad one cannot construct a loop like acantor’s digit loop for all the letters of the alphabet (there is no secret "increment" way of cycling through all letters, is there?). And more thinking out loud... perhaps, at the beginning, like "declarations," one could "hardwire" an array, with each consecutive item of the array assigned the next letter in the alphabet, like: Variable Set String %checkIfLetter[1]% "a" Variable Set String %checkIfLetter[2]% "b" Variable Set String %checkIfLetter[3]% "c" etc. etc. up to "z" One could then cycle through the items in the array: Variable Set String %x%: Prompt Variable Set Integer %counter% to 1 Repeat Until %checkIfLetter[%counter%]% Equals "z" If Variable %x% Contains "%checkIfLetter[%counter%]%" Text Box Display: "%x%" contains letters Macro Stop End If Variable Modify Integer %counter%: IncrementEnd Repeat Text Box Display: "%x%" does NOT contain letters Just thinking... Quote Link to comment Share on other sites More sharing options...
rberq Posted April 15, 2019 Report Share Posted April 15, 2019 35 minutes ago, MakaPakaTobyHannah said: Too bad one cannot construct a loop like acantor’s digit loop for all the letters of the alphabet (there is no secret "increment" way of cycling through all letters, is there?). See my suggestion above. Because the ASCII codes for all letters are grouped in a single range, you can code two IF statements instead of twenty-six. I think that will work. Variable Modify String (the one character you are examining) to upper case IF character greater than or equal to A AND IF character less than or equal to Z then it is alpha END IF http://www.columbia.edu/kermit/ascii.html Quote Link to comment Share on other sites More sharing options...
MakaPakaTobyHannah Posted April 16, 2019 Author Report Share Posted April 16, 2019 That’s a good idea. One would have to know which character in the string to look for. The strings can have different numbers of characters (including letters and digits) occurring anywhere in the string. With the IF statement you constructed, one can examine only one character at a time; so you’d have to step through each character of the string in succession (with a procedure to determine when the end of the string is reached). That’s doable. My approach is more of a brute force solution, but it permits examining the entire text string at once to see if anywhere in the string is any letter at all. So "9y3" would be identified immediately. Thanks for all the good ideas! Quote Link to comment Share on other sites More sharing options...
acantor Posted April 17, 2019 Report Share Posted April 17, 2019 I wrote the good folks at Insight Software to ask about the upper limit of characters when assigning string variables. Variable Set String %x%: Prompt The upper limit is 6,832 characters (including spaces), at least when the characters are pasted into the field. Variable Set String %Test% to "[very long string]" I've tested this with strings of up to 1,000,000 characters long without problems. Quote Link to comment Share on other sites More sharing options...
rberq Posted April 17, 2019 Report Share Posted April 17, 2019 13 hours ago, acantor said: I've tested this with strings of up to 1,000,000 characters long without problems. The only problem I recall with long string variables, was saving them in Environment Variables. I think I hit a problem at 8,192 bytes -- but I don't really remember for sure. Quote Link to comment Share on other sites More sharing options...
acantor Posted April 17, 2019 Report Share Posted April 17, 2019 Oops, there was a logic flaw in my original script. It wasn't testing for the presence of 9! I just tried this revised script with a string consisting of 1,200,000 characters, and it instantly reports if the string contains a digit or not. Variable Set String %x% to "[insert your string here]" Variable Set Integer %y% to the length of variable %x% Text Box Display: The string contains %y% characters Variable Set Integer %Digit% to 0 Repeat Until %Digit% Is Greater Than "9" If Variable %x% Contains "%Digit%" Text Box Display: YES, the string contains at least one digit Macro Stop Else Variable Modify Integer %Digit%: Increment End If End Repeat Text Box Display: NO, the string does not contain any digits Quote Link to comment Share on other sites More sharing options...
rberq Posted April 17, 2019 Report Share Posted April 17, 2019 Yeah, I saw your logic flaw but I didn't want to be obnoxious by pointing it out. So I'm being obnoxious now, instead. 🙃 If your macro is scanning 1.2MB almost instantly, your PC must be faster than my 7-year-oldie. Either that, or ME Pro maybe isn't doing the IF CONTAINS the same as ME 3. Quote Link to comment Share on other sites More sharing options...
acantor Posted April 17, 2019 Report Share Posted April 17, 2019 My computer is about three years old, with a 4th Generation Intel Core i7 CPU. The latest CPUs are 9th Generation. When opening the "set string" line to edit text consisting of hundreds of thousands of characters, I wait minutes! In fact, Macro Express freezes and becomes unresponsive. After two or three minutes, Macro Express rights itself. I would be curious to know how long my code takes to run on your computer with, say, a string of 5000 characters. Quote Link to comment Share on other sites More sharing options...
rberq Posted April 17, 2019 Report Share Posted April 17, 2019 5 hours ago, acantor said: I would be curious to know how long my code takes to run on your computer with, say, a string of 5000 characters. My processor is Intel Core i3-2370M CPU @ 2.40GHz 2.40GHz. I don't know what that means. Here's the ME routine I tested with. I built a Notepad document so I could easily modify the number of characters for tests. The first couple lines, copying to clipboard, took no more than a second or so, even with 500,000 characters. Setting string T1 from the clipboard took many seconds, maybe 15 or 20 seconds, with 500,000 characters. Very fast with only 5,000 characters. Displaying the "release" text box allows estimating the actual scan time (your code) -- that is, from the time I hit ENTER to close the "release" box, until either the "contains" or "contains none" box appears. So, to finally answer your question, your code runs almost instantaneously whether I start with 5,000 characters or with 500,000. I used Macro Return rather than Macro Stop like you did, but I doubt that matters much. // Text Type: <CTRLD>a<CTRLU> Macro Run: 0_Generic_Copy_To_Clipboard Variable Set String %T1% from Clipboard Text Type: <END> Text Box Display: release to start process Variable Set Integer %N1% to 0 Repeat Until %N1% > 9 If Variable %T1% contains "%N1%" Text Box Display: contains Macro Return Else Variable Modify Integer: Inc (%N1%) End If Repeat End Text Box Display: contains no digits Macro Return // 1 Quote Link to comment Share on other sites More sharing options...
acantor Posted April 18, 2019 Report Share Posted April 18, 2019 Your approach gave me an idea of another way to handle the input data, but without using the clipboard. Create a plain text file that consists of one line. I used Notebook to create the file. I inserted a string of 600,000 characters on one line. (PS: I typed 10 characters, selected everything and copied, and pasted ten times. Then I repeated the process until there are 1000 characters, then 10,000, then 100,000. It takes but a minute to generate hundreds of thousands, or millions, of characters.) Then the script uses "Text File Begin Process." I specified the variable to receive the information, and chose "Process All Records" beginning on record 1. It takes time to save the file, but once it has been saved, the macro runs almost instantly (at least on my computer). Text File Begin Process: C:\Users\Me\Documents\tmptmp.txt Text File End Process Variable Set Integer %y% to the length of variable %x% Text Box Display: %y% Variable Set Integer %Digit% to 0 Repeat Until %Digit% Is Greater Than "9" If Variable %x% Contains "%Digit%" Text Box Display: YES, contains at least one digit Macro Stop Else Variable Modify Integer %Digit%: Increment End If End Repeat Text Box Display: NO, does not contain any digits 1 Quote Link to comment Share on other sites More sharing options...
rberq Posted April 18, 2019 Report Share Posted April 18, 2019 Yes, the time-consuming thing seems to be getting the data into a ME variable. Scanning for "contains" is very fast. You built your 600K test string about the same way I did. So I guess I can't get you to hire me starting at one penny a day, if you will double my salary every day for a year. Quote Link to comment Share on other sites More sharing options...
acantor Posted April 19, 2019 Report Share Posted April 19, 2019 4 hours ago, rberq said: So I guess I can't get you to hire me starting at one penny a day, if you will double my salary every day for a year. When I was 13 years old, I participated in a 32 mile charity walk. Friends and family members pledged a penny or two or three per mile, but my Dad pledged one cent for Mile 1, two cents for Mile 2, four cents the Mile 3, etc. After completing the walk, one of my friends (who was perhaps a bit more mathematically inclined than I was) realized something was amiss, and sat down at his desk in our Grade 7 class with pencil and paper. It took him about half and hour to work out that my Dad had committed to contributing $42,949,672.95 to charity! My Dad wrote a cheque for $25, which was a lot of money in those days. A friend from a well-off family had pledged 5 cents per mile, and gave me $1.60! Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.