Here’s a subroutine which does the same. I got this code from this forum, unfortunately I forget who wrote it. Anyway, I tested the speed of this approach versus the do shell script approach using the “GetMilliSec subroutine and the Lotsa method”. Here’s the results.
Each test was run 500 times
the string I used in the test was “make this upper case.”
do shellscript “echo " & theString & " | tr a-z A-Z” → 11.368 secs
makeCaseUpper(theString) → 0.894 secs
Results: the subroutine is about 13 times faster than the do shell script command.
on makeCaseUpper(theString)
set UPPERCASE to "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
set lowercase to "abcdefghijklmnopqrstuvwxyz"
set AppleScript's text item delimiters to " "
set theWords to text items of theString as list
set AppleScript's text item delimiters to ""
set newList to {}
repeat with theWord in theWords
set chrs to characters of theWord
set Nchrs to count chrs -- get the number of characters
repeat with K from 1 to Nchrs
if (item K of chrs) is in lowercase then
set olc to offset of (item K of chrs) in lowercase
set item K of chrs to character olc of UPPERCASE
end if
end repeat
set end of newList to chrs as string
end repeat
set AppleScript's text item delimiters to " "
set theString to newList as string
set AppleScript's text item delimiters to ""
return theString
end makeCaseUpper
on ToggleCase(theString)
set theString to ASCII number of theString
if theString ≥ 65 and theString ≤ 90 then set theString to ASCII character of (theString + 32)
if theString ≥ 97 and theString ≤ 122 then set theString to ASCII character of (theString - 32)
return theString
end ToggleCase
Not sure if it is faster than the other option, would be interesting to see some time tests.
on my Dual G5 at work it this script takes about 8 seconds to loop 10,000 times
on ToggleCase(theString)
set theString to ASCII number of theString
if theString ≥ 65 and theString ≤ 90 then set theString to ASCII character of (theString + 32)
return theString
end ToggleCase
set x to current date
set p to "make this upper case."
repeat with i from 1 to 10000
repeat with q from 1 to count of characters of p
set z to ToggleCase(character q of p)
end repeat
end repeat
set y to current date
set y to y - x
Interesting idea Jerome. I made a few changes to your code toget it to change the case to UPPER as this discussion requests. Here’s what I came up with.
set theString to "make this upper case"
set chrs to characters of theString
set toggleList to {}
repeat with i from 1 to (count of chrs)
my caseUPPER(item i of chrs)
set end of toggleList to result
end repeat
set toggleString to toggleList as string
on caseUPPER(chr)
set asciiNum to ASCII number of chr
if asciiNum ≥ 97 and asciiNum ≤ 122 then set chr to ASCII character of (asciiNum - 32)
return chr
end caseUPPER
So I ran the “GetMilliSec subroutine and the Lotsa method” again on this modified method and the one I posted earlier.
Each test was run 500 times
the string I used in the test was “make this upper case.”
Jerome’s modified method → 0.719 secs
my makeCaseUpper(theString) → 0.875 secs
Results: Jerome’s modified method is about 20% faster than my subroutine.
Your comparison testing is wrong. One script uses ‘do shell script’ while the other one doesn’t. If the user has to use the do shell script and change to uppercase instead of piping the output to ‘tr’, then what are the times?
For this particular problem, yet another approach using offsets (slim 15% advantage over Regulus’, didn’t test the others):
makeCaseUpper("Now is the time, perhaps, for all good men")
on makeCaseUpper(theString)
set UC to "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
set LC to "abcdefghijklmnopqrstuvwxyz"
set C to characters of theString
repeat with ch in C
if ch is in LC then set contents of ch to item (offset of ch in LC) of UC
end repeat
return C as string
end makeCaseUpper
kel, I’m not sure what you mean? Piping the output to tr changes to upper case and uses the “do shell script” command. Which 2 comparisons do you mean?
What I mean is that the op wanted to convert shell output to uppercase. The call to the shell takes time, so you have to include that in the comparison. I use Jon’s Commands’ ‘the ticks’ in these:
Script 1 (pipe output to ‘tr’:
set t1 to the ticks
set t to do shell script "echo hello | tr '[:lower:]' '[:upper:]'"
set t2 to the ticks
display dialog (t2 - t1)
t
Script 2 (convert output to all uppercase with AppleScript):
set t1 to the ticks
set t to uppercase (do shell script "echo hello")
set t2 to the ticks
display dialog (t2 - t1)
t
Oh kel, I see what you meant. You wanted me to get the string for my test from the shell, thus comparing TR to my subroutine. My thought was that you could avoid the shell all together with my subroutine whereas with TR you couldn’t… but if you do need the shell to get the string then I see your point.
So here’s the results with the test kel suggested. In these two tests the shell generated the string to be converted to upper case, then that string was sent to either TR or the subroutine. The results were vastly different. I alsoi ncluded the actual code for the test. Note, anyone that wants to run this test needs to first install the GetMilliSec scripting addition… I found it on this website.
– results of 500 tests → {9.645, 7.059, 1.366340841479}
The first result is for piping to TR. it took 9.645 secs
The second reasult is for piping the string to the subroutine → it took 7.059 secs for about a 36% improvement.
So the two conclusions for the subroutine are:
36% improvement over TR when the shell generates the string
without using the shell to first generate your string you’ll see a 1300% improvement.
set Tests to RunTest() -- this kicks it off
----
on RunTest()
set lotsa to 500 -- the number of times the test will repeat
-- Any other preliminary values here.
-- Dummy loop to absorb a small observed time handicap in the first repeat.
repeat lotsa times -- warming up the engine.
end repeat
-- Test 1
set t to GetMilliSec
repeat lotsa times
-- test code or handler call here.
do shell script "echo hello | tr '[:lower:]' '[:upper:]'"
-- end of code fragment
end repeat
set t1 to ((GetMilliSec) - t) / 1000
-- Test 2
set t to GetMilliSec
repeat lotsa times
-- test code or handler call here.
my makeCaseUpper(do shell script "echo hello")
-- end of code fragment
end repeat
set t2 to ((GetMilliSec) - t) / 1000
-- Timings.
return {t1, t2, t1 / t2}
end RunTest
on makeCaseUpper(theString)
set UPPERCASE to "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
set lowercase to "abcdefghijklmnopqrstuvwxyz"
set AppleScript's text item delimiters to " "
set theWords to text items of theString as list
set AppleScript's text item delimiters to ""
set newList to {}
repeat with theWord in theWords
set chrs to characters of theWord
set Nchrs to count chrs -- get the number of characters
repeat with K from 1 to Nchrs
if (item K of chrs) is in lowercase then
set olc to offset of (item K of chrs) in lowercase
set item K of chrs to character olc of UPPERCASE
end if
end repeat
set end of newList to chrs as string
end repeat
set AppleScript's text item delimiters to " "
set theString to newList as string
set AppleScript's text item delimiters to ""
return theString
end makeCaseUpper
Yes, that’s what i meant. I found it interesting also, that Satimage osax’ ‘uppercase’ was about two times faster than piping the output to ‘tr’. I wonder what the times would be if you test it in Terminal. I don’t know how to do that though.