+74950000000
как вывести этот номер в формате +7(495)000-00-00
?
MobiDevices
7,2065 золотых знаков26 серебряных знаков66 бронзовых знаков
задан 28 июн 2021 в 12:55
5
Самый простой и короткий способ. Правда, не учитывает, введён ли номер с кодом, а также не учитывает 6-значный номер.
const validPhone = num => {
return num.replace(/^(d)(d{3})(d{3})(d{2})(d{2})$/, '+$1($2)$3-$4-$5')
}
console.log(validPhone('74950000000'))
ответ дан 28 июн 2021 в 13:30
MobiDevicesMobiDevices
7,2065 золотых знаков26 серебряных знаков66 бронзовых знаков
1
Очень прямолинейный и многосказательный вариант, но очевидный и простой!
let str = '+74950000000';
let plus_group = str.slice(0,2);
let code_group = str.slice(2,5);
let first_group = str.slice(5,8);
let second_group = str.slice(8,10);
let third_group = str.slice(10,12);
let correct_phone = plus_group + '(' + code_group + ')' + first_group + '-' + second_group + '-' + third_group;
console.log(correct_phone);
Можно использовать группы совпадений в регулярных выражениях:
let str = '+74950000000';
let gr = str.match(/(+d)(d{3})(d{3})(d{2})(d{2})/);
let correct_phone = gr[1] + '(' + gr[2] + ')' + gr[3] + '-' + gr[4] + '-' + gr[5];
console.log(correct_phone);
Можно подойти к вопросу более системно и использовать массив заполняющих знаков и reduce
для формирования строки:
let str = '+74950000000';
let signs = ['(',')','-','-'];
let groups = str.match(/(+d)(d{3})(d{3})(d{2})(d{2})/).slice(1,6);
let correct_phone = groups.reduce((str, gr, i)=> str + gr + (signs[i]||''),'');
console.log(correct_phone);
Или еще больше сократить выражение:
let str = '+74950000000';
let signs = ['(',')','-','-'];
let correct_phone = str.match(/(+d)(d{3})(d{3})(d{2})(d{2})/).slice(1,6).reduce((str, gr, i)=> str + gr + (signs[i]||''),'');
console.log(correct_phone);
ответ дан 28 июн 2021 в 13:06
LeonidLeonid
5,8075 серебряных знаков24 бронзовых знака
Доработал решение @Vadizar, поправил работу с плюсом.
const validPhone = num => {
return num.replace(/^+?(d)(d{3})(d{3})(d{2})(d{2})$/, '+$1($2)$3-$4-$5')
}
console.log(validPhone('74950000000'));
console.log(validPhone('+74950000000'));
ответ дан 28 июн 2021 в 17:05
PilatonPilaton
3,5458 золотых знаков11 серебряных знаков38 бронзовых знаков
Improve Article
Save Article
Improve Article
Save Article
Give a phone number and the task is to format a phone number in such a way that it becomes easy to understand for humans. There are two approaches to format the numbers which are discussed below:
Approach 1:
- A RegExp is used to replace the original phone number with a human-readable phone number.
- The RegExp is searching for the 3 digits and saves it in a variable($1 for the first 3 digits, $2 for the second 3 digits, and so on.)
- In the end, It is just concatenating them with ‘-‘ among them.
Example: This example implements the above approach.
html
<
script
src
=
</
script
>
<
h1
style
=
"color:green;"
>
GeeksforGeeks
</
h1
>
<
p
id
=
"GFG_UP"
>
</
p
>
<
button
onclick
=
"GFG_Fun()"
>
click here
</
button
>
<
p
id
=
"GFG_DOWN"
>
</
p
>
<
script
>
var up = document.getElementById('GFG_UP');
var down = document.getElementById('GFG_DOWN');
var phoneNo = '4445556678';
up.innerHTML = "Click on the button to format "
+ "the phone number.<
br
>Phone No: " + phoneNo;
function GFG_Fun() {
down.innerHTML =
phoneNo.replace(/(d{3})(d{3})(d{4})/,
'$1-$2-$3');
}
</
script
>
Output:
How to format a phone number in Human-Readable using JavaScript ?
Approach 2:
- This example is using the substr() method to format a phone number in Human-Readable format.
- It is taking a substrings of length 3 and putting ‘-‘ among them. Remaining string elements using the same method.
Example 2: This example implements the above approach.
html
<
script
src
=
</
script
>
<
h1
style
=
"color:green;"
>
GeeksforGeeks
</
h1
>
<
p
id
=
"GFG_UP"
>
</
p
>
<
button
onclick
=
"GFG_Fun()"
>
click here
</
button
>
<
p
id
=
"GFG_DOWN"
>
</
p
>
<
script
>
var up = document.getElementById('GFG_UP');
var down = document.getElementById('GFG_DOWN');
var phoneNo = '4445556678';
up.innerHTML = "Click on the button to format "
+ "the phone number.<
br
>Phone No: " + phoneNo;
function GFG_Fun() {
down.innerHTML =
down.innerHTML = phoneNo.substr(0, 3)
+ '-' + phoneNo.substr(3, 3)
+ '-' + phoneNo.substr(6, 4);
}
</
script
>
Output:
How to format a phone number in Human-Readable using JavaScript ?
Improve Article
Save Article
Improve Article
Save Article
Give a phone number and the task is to format a phone number in such a way that it becomes easy to understand for humans. There are two approaches to format the numbers which are discussed below:
Approach 1:
- A RegExp is used to replace the original phone number with a human-readable phone number.
- The RegExp is searching for the 3 digits and saves it in a variable($1 for the first 3 digits, $2 for the second 3 digits, and so on.)
- In the end, It is just concatenating them with ‘-‘ among them.
Example: This example implements the above approach.
html
<
script
src
=
</
script
>
<
h1
style
=
"color:green;"
>
GeeksforGeeks
</
h1
>
<
p
id
=
"GFG_UP"
>
</
p
>
<
button
onclick
=
"GFG_Fun()"
>
click here
</
button
>
<
p
id
=
"GFG_DOWN"
>
</
p
>
<
script
>
var up = document.getElementById('GFG_UP');
var down = document.getElementById('GFG_DOWN');
var phoneNo = '4445556678';
up.innerHTML = "Click on the button to format "
+ "the phone number.<
br
>Phone No: " + phoneNo;
function GFG_Fun() {
down.innerHTML =
phoneNo.replace(/(d{3})(d{3})(d{4})/,
'$1-$2-$3');
}
</
script
>
Output:
How to format a phone number in Human-Readable using JavaScript ?
Approach 2:
- This example is using the substr() method to format a phone number in Human-Readable format.
- It is taking a substrings of length 3 and putting ‘-‘ among them. Remaining string elements using the same method.
Example 2: This example implements the above approach.
html
<
script
src
=
</
script
>
<
h1
style
=
"color:green;"
>
GeeksforGeeks
</
h1
>
<
p
id
=
"GFG_UP"
>
</
p
>
<
button
onclick
=
"GFG_Fun()"
>
click here
</
button
>
<
p
id
=
"GFG_DOWN"
>
</
p
>
<
script
>
var up = document.getElementById('GFG_UP');
var down = document.getElementById('GFG_DOWN');
var phoneNo = '4445556678';
up.innerHTML = "Click on the button to format "
+ "the phone number.<
br
>Phone No: " + phoneNo;
function GFG_Fun() {
down.innerHTML =
down.innerHTML = phoneNo.substr(0, 3)
+ '-' + phoneNo.substr(3, 3)
+ '-' + phoneNo.substr(6, 4);
}
</
script
>
Output:
How to format a phone number in Human-Readable using JavaScript ?
Day 4 of 365 Days of Coding challenge!
Disclaimer: there are MANY ways to solve this problem this is an answers that I would see or use in a coding interview and would accept as a proper answer
TLDR: Solution is at the bottom of the post
The Problem
Write a function that accepts a string of numbers or a number and converts it to a US phone number format.
Examples:
phoneFormat(2359654144) phoneFormat('2359654144') phoneFormat([2359654144]) phoneFormat(1234) phoneFormat(23596541445) phoneFormat('235$96541445') phoneFormat([213]) phoneFormat(null)
Solution
Lets write out what we are going to need to do
-
create a function that accepts an input
-
check if the string is a number (doesn’t include characters or letters) and not null or undefined
-
check if the input is a string if not convert it into a string
-
check if the input length is 10 (us number is 10 digits)
-
if it is
-
format it to xxx-xxx-xxxx
-
-
if not check if it is less than 10
-
return error was not supplied enough numbers please pass a 10 digit number
-
if not check if length is greater than 10
-
return was supplied too many numbers please pass a 10 digit number
-
if not send something went wrong error for a catch all just in case
-
-
-
-
If you are unfamiliar with if statements please check out this MDN page before going any further.
First we need to create our function
const phoneFormat = (input) => { }
We need to check if the string is a number (doesn’t include characters or letters) and not null or undefined. To do this we are going to use isNaN(). NaN stands for not a number. the built in JavaScript function does count strings of only numbers as numbers. If you are not familiar with this please check out this MDN page before continuing.
We are also going to use a template literal to make our error a little more helpful if you are unfamiliar with template literals please read this MDN page.
const phoneFormat = (input) => { if(!input || isNaN(input)) return `input must be a number was sent ${input}` }
If our input is not a string we need to make it a string so we can do our transform. If you are not familiar with .toString() please check out this MDN page before continuing
const phoneFormat = (input) => { if(!input || isNaN(input)) return `input must be a number was sent ${input}` if(typeof(input) !== 'string') input = input.toString() }
Since US phone numbers are made up of 10 digits we need to check if our input is 10 digits
const phoneFormat = (input) => { if(!input || isNaN(input)) return `input must be a number was sent ${input}` if(typeof(input) !== 'string') input = input.toString() if(input.length === 10){ } }
If the input is 10 digits we need to format it into the phone number. If you are not familiar with .replace() please check out this MDN page. If you are not familiar with regex or would like to better understand it please check out this page. It is a great tool for testing and learning regex.
const phoneFormat = (input) => { if(!input || isNaN(input)) return `input must be a number was sent ${input}` if(typeof(input) !== 'string') input = input.toString() if(input.length === 10){ return input.replace(/(d{3})(d{3})(d{4})/, "$1-$2-$3"); } }
You will notice that I formatted my string with dashes between each section (“$1-$2-$3“) if you would rather have parenthesis on the first 3 digits instead you just need to make your string (“($1)$2-$3“) instead.
Going back to our if else statement, we are going to check if the input is less than 10. If you didn’t want your errors to be specific to the length you could have a simple if else statement that was if the length was 10 format otherwise return a message about it being an invalid input. However, I wanted to make my error messages more specific so first I am going to check if the input is less than 10 and if it is return a message asking the user to supply a 10 digit number. We could so a template literal here and let them know what they did supply but I decided letting them know they didn’t supply enough numbers was enough. If you wanted to send them what they did supply you can reference the message sent in our isNaN check.
const phoneFormat = (input) => { if(!input || isNaN(input)) return `input must be a number was sent ${input}` if(typeof(input) !== 'string') input = input.toString() if(input.length === 10){ return input.replace(/(d{3})(d{3})(d{4})/, "$1-$2-$3"); } else if(input.length < 10){ return 'was not supplied enough numbers please pass a 10 digit number' } }
If the input isn’t less than 10 we are going to check if the input is greater than 10. Some people may just put an else here and return the message for is greater than 10. This is okay however, in other instances I have seen thing other than the logic checks be wrong and then you are sending the wrong error back. For instance, if something was wrong other than the length of the string that the other logic didn’t catch we would get a message saying ‘was supplied too many numbers please pass a 10 digit number’ when in fact that wasn’t the issue. For this simple example that is probably fine as I can’t think of much that would be wrong that we don’t have logic for but its always good to have a catch all error just in case so I am adding a specific check for greater than 10.
const phoneFormat = (input) => { if(!input || isNaN(input)) return `input must be a number was sent ${input}` if(typeof(input) !== 'string') input = input.toString() if(input.length === 10){ return input.replace(/(d{3})(d{3})(d{4})/, "$1-$2-$3"); } else if(input.length < 10) { return 'was not supplied enough numbers please pass a 10 digit number' } else if(input.length > 10) { return 'was supplied too many numbers please pass a 10 digit number' } }
Now all we need is our catch all error and we are all good!
const phoneFormat = (input) => { if(!input || isNaN(input)) return `input must be a number was sent ${input}` if(typeof(input) !== 'string') input = input.toString() if(input.length === 10){ return input.replace(/(d{3})(d{3})(d{4})/, "$1-$2-$3"); } else if(input.length < 10) { return 'was not supplied enough numbers please pass a 10 digit number' } else if(input.length > 10) { return 'was supplied too many numbers please pass a 10 digit number' }else{ return 'something went wrong' } }
Please leave your solutions that you came up with in the comments section. If you have any challenge you would like to see done also leave that in the comments below you may see it come up! If you would like to get the challenge emailed to you every day in morning and a notification when the solution is posted subscribe below
Такая элементарная вещь, как номер телефона, в письменных текстах живёт во множестве вариантов. Обыкновенный номер типа +7 (123) 123-45-67
можно встретить записанным без скобок или дефисов (+7 123 1234567
), а то и вообще без пробелов (+71231234567
). Не собираюсь оскорблять чувства пишущих, им и так непросто. Но уважающий себя веб-ресурс не может допустить такой типографической разношёрстности. Плюс к тому, необлагороженные номера неудобно читать человеку (то самое human-readable).
Данная статья о том, как привести все телефонные номера на странице к однообразному виду, а также проставить корректные ссылки типа tel:
на них. Для решения поставленной задачи используются регулярные выражения JavaScript. Хороший обзор регэкспов дан здесь, также почитать по теме можно на MDN.
В качестве эталонной будет принята запись номера вида +7 (123) 123-45-67
.
Найти все телефонные номера на странице можно таким способом:
let pattern = new RegExp('(+7|8)[s(]*d{3}[)s]*d{3}[s-]?d{2}[s-]?d{2}', 'g'); // создать регулярное выражение
let phoneNumbers = document.body.innerText.match(pattern); // применить на всём тексте документа
Метод match()
вернёт и запишет в переменную phoneNumbers
массив (объект типа Array
) со всеми найденными на странице номерами.
Дисклеймер. Виденное выше регулярное выражение может вызвать сильное чувство боли в глазах у неподготовленного читателя. Если вы не очень знакомы с регулярками, автор всё-таки советует для начала проработать несколько первых глав учебника на LearnJavascript.
Разберём это выражение:
(+7|8) |
+7 (123) 123-45-67
На практике встречается начало и с
Напомню: |
[s(]*d{3}[)s]* |
+7 (123) 123-45-67 |
[s(]* |
+7 (123) 123-45-67
То есть, фактически, эти части паттерна распознают первые три цифры после кода страны, причём как взятые в скобки, так и без (квантификатор
Также напомню: |
d{3}[s-]?d{2}[s-]?d{2} |
+7 (123) 123-45-67 |
[s-]? |
+7 (123) 123—45—67
Данная часть паттерна распознаёт последние 7 цифр номера. Они могут быть разделены дефисами, пробелами или вообще ничем.
Наверное, уже нет смысла пояснять, что цифра, взятая в фигурные скобки |
Ну хорошо, найти все номера получилось. К сожалению, задача этим не исчерпывается. Как же взять и заменить все вхождения разом?
Здесь поможет метод replace()
. Если у регулярного выражения указан флаг 'g'
(второй аргумент конструктора), то replace()
заменит все вхождения на то, что указано. Например, задача замены всех повторяющихся пробелов в тексте на одинарные решается таким простым способом:
text = text.replace(/s{1,}/g, ' ');
На всякий: /s{1,}/g
— это краткая запись для new RegExp('s+', 'g')
. Также вместо {1,}
можно писать просто +
.
Но ведь у нас задача сложнее: нельзя же заменить разные номера телефонов на один! Тут самое время вспомнить о скобочных группах.
Скобочная группа — термин из теории регулярных выражений. Технически это просто часть паттерна, взятая в скобки. Но к любой такой группе можно обратиться по индексу.
Получается,
К счастью, replace()
поддерживает работу с группами. Достаточно написать в шаблоне замены (второй параметр) ${номер_группы}
($1
или $5
), и функция заменит эту конструкцию на содержимое скобочной группы.
То была идея, а теперь реализация:
let pattern = /(+7|8)[s(]?(d{3})[s)]?(d{3})[s-]?(d{2})[s-]?(d{2})/g; // паттерн с проставленными скобками
let phoneNumbers = document.body.innerText.match(pattern); // найдём все номера
let correctNumber = phoneNumbers[0].replace(pattern, '+7 ($2) $3-$4-$5'); // пробуем замену
console.log(correctNumber);
В результате будет выведен аккуратный, каноничный телефонный номер. Работает!
Теперь, чтобы заменить все найденные номера телефонов на единообразные, добавим флаг g
:
let pattern = /(+7|8)[s(]?(d{3})[s)]?(d{3})[s-]?(d{2})[s-]?(d{2})/g;
document.body.innerHTML = document.body.innerHTML.replace(pattern, '+7 ($2) $3-$4-$5');
Усложним шаблон функции replace()
, чтобы номер телефона был кликабельным (ссылка с префиксом tel:
):
let pattern = /(+7|8)[s(]?(d{3})[s)]?(d{3})[s-]?(d{2})[s-]?(d{2})/g;
document.body.innerHTML = document.body.innerHTML.replace(pattern, '<a href="tel:+7$2$3$4$5">+7 ($2) $3-$4-$5</a>');
То есть, для корректной работы ссылки нужно в её коде выписать все цифры номера подряд — как раз самый неудобный для чтения человеком вариант.
11.03.2012, 03:24 |
||||
|
||||
Форматирование вводимого номера + 7 123 456-78-90 Хочу сделать чтобы при вписывании номера в input происходило вот такое незамысловатое форматирование. Впринципе важно чтобы все работало при вручном вводе номера, корректная работа backspace. На вставку из буфера можно забить — врядли кто-то будет этим пользоваться. |
11.03.2012, 04:11 |
||||
|
||||
по кейпрессу вызываешь функцию, которая сразу ставит плюс и пробел, дальше проверяет позицию каретки (курсора). если 3 (плюс уже занимает первое место, пробел — второе) — к значению поля (value) добавляешь ещё один пробел, если 7 — тоже самое (добавляешь пробел), если 11 — добавляешь дефис, и если 14 — тоже дефис.
__________________ |
11.03.2012, 05:55 |
|||
|
|||
var numbers = [ "+71234567890", "1234567890", "234567890", "34567890", "4567890", "567890", "67890", "7890", "890", "90", "0" ] var re = /(?:([d]{1,}?))??(?:([d]{1,3}?))??(?:([d]{1,3}?))??(?:([d]{2}))??([d]{2})$/; for( var i = 0; i < numbers.length; i++ ) { var formatted = numbers[ i ].replace( re, function( all, a, b, c, d, e ){ return ( a ? a + " " : "" ) + ( b ? b + " " : "" ) + ( c ? c + "-" : "" ) + ( d ? d + "-" : "" ) + e; }); alert( formatted ); }
|
11.03.2012, 06:21 |
|||
|
|||
Чушь конечно получилась, ну и фиг с ним <input type="text" onkeyup="handler( this )" oninput="handler( this )" onblur="handler( this )" /> <script> var re = /(?:([d]{1,}?))??(?:([d]{1,3}?))??(?:([d]{1,3}?))??(?:([d]{2}))??([d]{2})$/; function handler( elem ) { elem.value = elem.value.replace( /[^0-9]/g, '' ).replace( re, function( all, a, b, c, d, e ){ return ( a ? "+ " + a + " " : "" ) + ( b ? b + " " : "" ) + ( c ? c + "-" : "" ) + ( d ? d + "-" : "" ) + e; }); } </script>
|
11.03.2012, 10:05 |
||||
|
||||
еще вариант <input type="text" onkeyup="formattingNumbers( this )"> <script> function formattingNumbers( elem ) { var num = elem.value.replace( /D/g, '' ).split( /(?=.)/ ), i = num.length - 1; if ( 0 <= i ) num.unshift( '+ ' ); if ( 1 <= i ) num.splice( 2, 0, ' ' ); if ( 4 <= i ) num.splice( 6, 0, ' ' ); if ( 7 <= i ) num.splice( 10, 0, '-' ); if ( 9 <= i ) num.splice( 13, 0, '-' ); elem.value = num.join( '' ); } </script>
__________________ |
11.03.2012, 14:18 |
||||
|
||||
Вариант … <!DOCTYPE html> <html> <head> <title></title> </head> <body> <input type="text" onkeyup="formattingNumbers( this )" value="+ 7 "> <script> function formattingNumbers(b) { var a = "+ 7 123 456-78-90", c = b.value.match(/d/g); if(!c) return b.value = "+ 7 "; a = a.replace(/d/g, function () { return c.shift() || "#" }); b.value = a.replace(/#.*/, "") };</script> </body> </html>
|
11.03.2012, 16:17 |
||||
|
||||
Благодарю всех. |
11.03.2012, 17:02 |
||||
|
||||
А что вот это такое? ‘string’.split( /(?=.)/ ) — это такой способ преобразования строки в массив? Кстати чтобы заработал бэкспейс в вариант от рони, достаточно использовать такую регулярку |
11.03.2012, 20:07 |
||||
|
||||
danik.js, да не, рони нормальный вариант предложил, за что ему плюс в карму <input type="text" onkeyup="formattingNumbers( this )" value="+ 7 123 456-78-90"> <script> function formattingNumbers( elem ) { var pattern = '+ 7 123 456-78-90', arr = elem.value.match( /d/g ), i = 0; if ( arr === null ) return; elem.value = pattern.replace( /d/g, function( a, b ) { if ( arr.length ) i = b + 1; return arr.shift(); }).substring( 0, i ); } </script>
__________________
|
11.03.2012, 20:13 |
||||
|
||||
Как то понравился ваш вариант, nerv, хотя у рони задать паттерн можно. Вобщем вроде бы разобрался в обоих способах, особой разницы для меня нет что использовать. Выложу окончательный вариант, вдруг кому понадобится (jQuery) : $.fn.formatPnoneNumber = function(){ return this.each(function(){ $(this).bind('keyup', function(){ var num = this.value.replace( '+ 7' , '' ).replace( /D/g, '' ).split( /(?=.)/ ), i = num.length; if ( 0 <= i ) num.unshift( '+ 7' ); if ( 1 <= i ) num.splice( 1, 0, ' ' ); if ( 4 <= i ) num.splice( 5, 0, ' ' ); if ( 7 <= i ) num.splice( 9, 0, '-' ); if ( 9 <= i ) num.splice( 12, 0, '-' ); if ( 11 <= i ) num.splice( 15, num.length - 15 ); this.value = num.join( '' ); }); }); };
|