Alphanumeric Phone Number Converter

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

Hi Rob,

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.

Best wishes

John Maisey
www.nhoj.co.uk

Another method:

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"

:wink:
Well, if we want to get really fancy:

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

Alternatively:

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"

:smiley:
I shortened mine:

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 had to change “txt” to tText on my system (txt is perceived as an AppleScript word by Script Debugger 4), but it works as advertised. :wink:

I’m surprised that no one has produced a sed/regex method. :o

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"

I like these creative threads :lol:

I do too, Stefan; it’s amazing how often you learn something when the problem itself isn’t the barrier.

Thanks for all the different scripts! Awesome forum! :slight_smile:

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!

Speed test conducted as outlined by Nigel Garvey in post 4 found here: http://bbs.applescript.net/viewtopic.php?id=17015

time: measured in seconds
iterations: 500
computer: dual 2GHz G5 PPC
phone number: “1-800-Abc-def-gHi-jkl-mno-pQrs-tuv-wxyz”

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.

Oops! I missed that.

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

And the obligatory shell script way…

#!/bin/bash
time /usr/bin/osascript <<EOT
tell application “Some App”
–do something
end tell
EOT

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.