The following script takes an alphanumeric phone number and returns the numeric equivalent. I’m wondering if there’s an easier or more elegant or shorter script that will do the same thing. Thanks.
set myText to "1-800-GoFedEx"
set myNumber to ""
repeat with i from 1 to the count of myText
if character i of myText is "a" or character i of myText is "b" or character i of myText is "c" then
set i to "2"
else if character i of myText is "d" or character i of myText is "e" or character i of myText is "f" then
set i to "3"
else if character i of myText is "g" or character i of myText is "h" or character i of myText is "i" then
set i to "4"
else if character i of myText is "j" or character i of myText is "k" or character i of myText is "l" then
set i to "5"
else if character i of myText is "m" or character i of myText is "n" or character i of myText is "o" then
set i to "6"
else if character i of myText is "p" or character i of myText is "q" or character i of myText is "r" or character i of myText is "s" then
set i to "7"
else if character i of myText is "t" or character i of myText is "u" or character i of myText is "v" then
set i to "8"
else if character i of myText is "w" or character i of myText is "x" or character i of myText is "y" or character i of myText is "z" then
set i to "9"
else
set i to character i of myText
end if
set myNumber to myNumber & i
end repeat
I don’t see that much wrong with your approach. However here’s an alternative.
set myText to "1-800-GoFedEx"
set myNumber to ""
set myAlphabet to "abc def ghi jkl mno pqrstuv wxyz"
repeat with i in myText
if (myAlphabet contains i) and (i does not contain " ") then
set i to (((offset of i in myAlphabet) - 1) div 4) + 2
end if
set myNumber to myNumber & i
end repeat
return myNumber
It relies on the spacing of the letters in the variable myAlphabet.
set myText to "1-800-gofedex"
set myNumber to ""
set myAlphabet to "1234567890abcdefghijklmnopqrstuvwxyz-"
set mynumbs to "123456789022233344455566677778889999-"
repeat with i in myText
set x to offset of i in myAlphabet
set i to text x thru x of mynumbs
set myNumber to myNumber & i
end repeat
return myNumber
-- Couldn't resist --
set myText to "1-800-gofedex"
set tNum to ""
set pad to "1234567890abcdefghijklmnopqrstuvwxyz- "
set N to "123456789022233344455566677778889999- "
set k to 0
repeat with i in myText
set k to k + 1
if k is 10 then
set tNum to tNum & "-" & character (offset of i in pad) of N
else
set tNum to tNum & character (offset of i in pad) of N
end if
end repeat
return tNum --> "1-800-463-3339"
set myText to "1800gofedex"
set myNumber to ""
set myAlphabet to "1234567890abcdefghijklmnopqrstuvwxyz-"
set mynumbs to "123456789022233344455566677778889999-"
repeat with i in myText
set x to offset of i in myAlphabet
set i to text x thru x of mynumbs
set myNumber to myNumber & i
end repeat
set dash to text -4 thru -4 of myNumber
if dash is not "-" then
set myNumber to text 1 thru -5 of myNumber & "-" & text -4 thru -1 of myNumber
end if
set len to length of myNumber
if len > 8 then
set dash to text -9 thru -9 of myNumber
if dash is not "-" then
set myNumber to text 1 thru -9 of myNumber & "-" & text -8 thru -1 of myNumber
end if
end if
set len to length of myNumber
if len > 12 then
set dash to text -13 thru -13 of myNumber
if dash is not "-" then
set myNumber to text 1 thru -13 of myNumber & "-" & text -12 thru -1 of myNumber
end if
end if
return myNumber
Try it with:
gofedex
1800gofedex
1-800-gofedex
800gofedex
on convertAlphanumericPhoneNumber(phoneNumber)
set theResult to ""
repeat with thisChar in phoneNumber
-- set thisID to id of thisChar
set thisID to ASCII number thisChar
if thisID < 65 or (thisID > 91 and thisID < 97) or thisID > 123 then
set theResult to theResult & thisChar
else
-- Adjust lower case letters
if thisID ≥ 97 and thisID ≤ 123 then set thisID to thisID - 32
-- Number letters from 0 to 25
set thisID to thisID - 65
-- Account for the different amount of letters on 7 and 9
if thisID is in {18, 21, 24} then
set thisID to thisID - 1
else if thisID is 25 then
set thisID to 23
end if
set theResult to theResult & ((thisID div 3) + 2)
end if
end repeat
return theResult
end convertAlphanumericPhoneNumber
convertAlphanumericPhoneNumber("1-800-abc-def-ghi-jkl-mno-pqrs-tuv-wxyz")
--> "1-800-222-333-444-555-666-7777-888-9999"
set myText to "800GoFedex"
set myNumber to ""
set myAlphabet to "1234567890abcdefghijklmnopqrstuvwxyz-"
set mynumbs to "123456789022233344455566677778889999-"
set txtindx to {-4, -8, -12}
repeat with i in myText
set x to offset of i in myAlphabet
set i to text x thru x of mynumbs
set myNumber to myNumber & i
end repeat
repeat with ind in txtindx
set len to length of myNumber
if len > (-ind) then
set dash to text -ind thru -ind of myNumber
if dash is not "-" then
set myNumber to text 1 thru (ind - 1) of myNumber & "-" & text ind thru -1 of myNumber
end if
end if
end repeat
return myNumber
Oops! I knew txt wasn’t a good variable name, especially since not a good description of its purpose. It’s more an index than text.
I edited txt to be txtindx.
I think that would be overkill. If I was going to use the shell, I would probably use tr:
on convertAlphanumericPhoneNumber(phoneNumber)
do shell script "echo " & quoted form of phoneNumber & ¬
" | /usr/bin/tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz' '2223334445556667777888999922233344455566677778889999'"
end convertAlphanumericPhoneNumber
convertAlphanumericPhoneNumber("1-800-abc-def-ghi-jkl-mno-pqrs-tuv-wxyz")
--> "1-800-222-333-444-555-666-7777-888-9999"
on convertAlphanumericPhoneNumber(phoneNumber)
do shell script "echo " & quoted form of phoneNumber & ¬
" | /usr/bin/tr '[:upper:]' '[:lower:]'" & ¬
" | /usr/bin/tr 'abcdefghijklmnopqrstuvwxyz' '22233344455566677778889999'"
end convertAlphanumericPhoneNumber
convertAlphanumericPhoneNumber("1-800-abc-def-ghi-jkl-mno-pqrs-tuv-wxyz")
--> "1-800-222-333-444-555-666-7777-888-9999"
This thread proves the saying “there’s more than one way to skin a cat”!
Anyway I was curious because my thought is to just use text item delimiters but I know it’s boring. So my method is below… but I got to wondering which of these methods was the fastest. So I ran some speed tests on them. Here’s the results, and they prove boring isn’t always a bad thing!
RESULTS:
post 1: 17.365
post 2: 4.788
post 3: 4.346
post 4: 3.771
post 6: 4.218
post 9a: 11.622
post 9b: 12.473
post 13: 1.053
– these two returned the wrong value because the input string was too long, but I timed them anyway as is
post 5: 93.382
post 7: 97.123
set myAlphabet to "abcdefghijklmnopqrstuvwxyz"
set mynumbs to "22233344455566677778889999"
set phoneNumber to "1-800-Abc-def-gHi-jkl-mno-pQrs-tuv-wxyz"
repeat with i from 1 to count of myAlphabet
set phoneNumber to findReplace(phoneNumber, (item i of myAlphabet), (item i of mynumbs))
end repeat
phoneNumber
on findReplace(theString, search_string, replacement_string)
if theString contains search_string then
set AppleScript's text item delimiters to search_string
set text_item_list to text items of theString
set AppleScript's text item delimiters to replacement_string
set theString to text_item_list as string
set AppleScript's text item delimiters to ""
end if
return theString
end findReplace
These two attempt to put the number into a normal telephone number format: 1-XXX-XXX-XXXX
I don’t know how you got 90+ seconds though, they finish in the blink of an eye on my dual G5, even with the extra long phone number.
I just ran it again to make sure. When I run your post#7 script as-is it takes 15 seconds, but when I put in the long number I used for the test the time goes to 96 seconds.
You have to remember I’m doing the test 500 times, so that’s actually only less than .2 seconds per test, so it does finish in the blink of an eye for 1 test. You can run the test too. If you don’t have the getMilliSec osax then just substitute the current date to calculate time. I only use the osax to measure time in smaller increments than 1 second.
For those of you running G5’s who have GetMilliSec installed, here’s a handy testing setup devised by Nigel Garvey:
For those of you running on Intel machines (where GetMilliSec doesn’t work), StefanK has written an equivalent timer he calls RefMilliSec
set Ratios to lotsa(500) -- the number of runs
on lotsa(many)
-- Any preliminary or common values here.
-- Dummy loop to absorb a small observed
-- time handicap in the first repeat.
repeat many times
end repeat
-- Test 1.
set t to GetMilliSec
repeat many times
-- First test code or handler call here.
end repeat
set t1 to ((GetMilliSec) - t) / 1000
-- Test 2.
set t to GetMilliSec
repeat many times
-- Second test code or handler call here.
end repeat
set t2 to ((GetMilliSec) - t) / 1000
-- Timings.
return {t1, t2, t1 / t2, t2 / t1}
end lotsa
Great catch. You’re absolutely right. Your explanation for the 90+ second tests are correct too. I was running so many tests that I didn’t pay close enough attention… that’s why I listed the test and the testing parameters so people could verify stuff. I’m glad you caught those errors.