I am trying to find the simplest (or at least shortest) method that does the following:
take any text from an input field and convert it as follows:
abc => 2
def => 3
ghi => 4
...
wxyz => 9
*any other character that is not part of the English alphabet is converted to '#' (or any other special character).
This may sound simple but the code can be made very simple and elegant and that is what I am looking for, fewer lines of php or js/jquery method. If it converts "abc", "def", I can finish the rest. Thank you for any help!
Build an associative array that maps A onto 2, B onto 2, C onto 2, D onto 3, etc.
Iterate through the string, one character at a time. If a character is found in the array, concatenate it to your output; if not concatenate "#" to the output. You will probably want to convert the string to all uppercase or all lowercase first.
Edited to add: I didn't include code because it appears that the OP knows JavaScript and PHP, and of course, the code would be different, but the principles are the same.
If one is absolutely, positively sure that the string is in ASCII/UTF-8/ISO-8859, one could make use of the fact that the uppercase letters occupy code points 65 to 90 decimal, and that three letters are assigned to each number from 2 to 9 and so compute the result. (Note that Q is missing from U.S. telephones and Z maps to zero.) However, this is not so much elegant as excessively tricky.
Earlier today I was reminded of this:
“Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.” -- Brian Kernighan and P.J. Plauger, The Elements of Programming Style
You can use str_replace($searchArr, $replaceArr, $string)
to replace anything in the "search array" with the corresponding value in the "replacement array". And you can populate those arrays like this:
$string = "dhebfctgddekj";
$pattern = array();
$replacement = array();
for($i = 97; $i < 123; $i++) //Ascii 97 = a to ascii 122 = z
{
$pattern[] = chr($i); //Convert the ascii to a character
}
$r = array(3,3,3,3,3,4,3,4); //How many characters each number has
$j = 2;
foreach($r as $val)
{
for($i = 0; $i < $val; $i++)
$replacement[] = $j;
$j++;
}
$string2 = str_replace($pattern, $replacement, strtolower($string));
echo $string2;
$subject = '0900ABCDEF'
$ReplacementPattern = array(
'a' => '2',
'b' => '2',
'c' => '2',
'd' => '3',
'e' => '3',
'f' => '3',
'g' => '4',
'h' => '4',
'i' => '4',
'j' => '5',
'k' => '5',
'l' => '5',
'm' => '6',
'n' => '6',
'o' => '6',
'p' => '7',
'q' => '7',
'r' => '7',
's' => '7',
't' => '8',
'u' => '8',
'v' => '8',
'w' => '9',
'x' => '9',
'y' => '9',
'z' => '9',
'+' => '00',
' ' => '',
);
echo str_ireplace(array_keys($ReplacementPattern), array_values($ReplacementPattern), $subject);
One-liner in javascript:
phoneStr.replace(/./g, x =>
'22233344455566677778889999'[(x.charCodeAt()-65)%32] || x
);
You can do [x.toLowerCase().charCodeAt()-97]
if you want to be clearer.
Demo (stick above in appropriate-named function):
> phoneToKeypad('+1-800-abc-WXYZ')
"+1-800-222-9999"
You can also use Array.from(phoneStr, x => x)
to work with an Array representation if you need, then .join('')
it later back into a string.
Strip dirty inputs (e.g. hyphens, parentheses, etc.) as appropriate by preprocessing:
phoneStr.replace(/[^0-9*#+a-zA-Z]/g, '').replace( ... etcetc
Of course, you will need to do sanitize such on the server side, so you can't only rely on client-side javascript (unless your server is also in javascript).
The layout of a keypad is referred as ISO/IEC 9995-8. Do note however that (according to my very cursory research) there are a plethora of international standards, such as the 184-page ETSI ES 202 130 standard in Europe.
Here is a javascript function that I use to convert text to phone keypad number:
const textToKeypadNumber = (text) => {
const phoneCharMap = {
a: "2",
b: "2",
c: "2",
d: "3",
e: "3",
f: "3",
g: "4",
h: "4",
i: "4",
j: "5",
k: "5",
l: "5",
m: "6",
n: "6",
o: "6",
p: "7",
q: "7",
r: "7",
s: "7",
t: "8",
u: "8",
v: "8",
w: "9",
x: "9",
y: "9",
z: "9",
"+": "00",
" ": ""
};
const _text = text.split("");
return _text
.map(char => {
const number = phoneCharMap[char.toLowerCase()];
if (number) return phoneCharMap[char.toLowerCase()];
return char;
})
.join("");
}
Use like this:
textToKeypadNumber('1-800-MY-APPLE'); // 1-800-69-27753