Как мне переделать строку в блоки из 3-х цифр, разделенных тире (-) в JavaScript?
например:
let myString = "00 64 33 3-44-23 982- 23-1-0"
выдать желаемый результат:
myString = "006-433-344-239-822-310"
С регулярным выражением:
("00 64 33 3-44-23 982- 23-1-0").replace(/\D/g,"").replace(/(\d{3})(?!$)/g,'$1-')
Объяснение:
\D
- удалить все нецифровые символы
(\d{3})(?!$)
(\d{3})
- сопоставить 3 числа(?!$)
- но не последние 3 0 - 22 1985--324
в 022-198-53-24
:
("0 - 22 1985--324")
.replace(/\D/g,"") // strip numbers
.replace( // do specific format
/^(\d{3})(\d{3})(\d{2})(\d{2})$/g,
'$1-$2-$3-$4'
)
Сначала вы можете использовать "replace" для удаления любых символов без цифр с регулярным выражением.
let myString = "00 64 33 3-44-23 982- 23-1-0"
myString = myString.replace(/\D/g, "")
// "006433344239822310"
Во-вторых, "сопоставлять" любые цифры (0-9) между 1 и 3 раза. Функция соответствия удобно возвращает массив с элементом для каждого совпадения.
myString = myString.match(/\d{1,3}/g)
// [006,433,344,239,822,310]
Наконец, присоедините массив, используя "-" в качестве разделителя.
myString = myString.join("-");
// 006-433-344-239-822-310
И если вы хотите объединить каждый шаг вместе.
myString = myString.replace(/\D/g, "").match(/\d{1,3}/g).join("-");
Обратите внимание: если строка содержит оставшиеся цифры, они останутся в своем собственном блоке в конце строки. Это связано с 1-3 матчами.
Например..
"00 64 33 3-44-23 982- 23-1-0 24" // before - with 2 extra digits
"006-433-344-239-822-310-24" // after - the extra digits are maintained
Из того, что вы сказали в комментариях, я считаю, что вам нужны группы из 3, где это возможно, и группы из 2 в конце, если их недостаточно. Я верю, что это сделает это:
[
'1-2 3 45---67 890',
'12345678901',
'123456789012',
'1234567890123',
'12345678901234',
'1',
'12',
'123',
'1234',
'12345',
'123456',
'1234567'
].forEach(function(str) {
console.log(str.replace(/\D/g, '').replace(/(\d\d\d?)(?=\d\d)/g, '$1-'));
});
/\D/g
удаляет все разряды без цифр. Группа захвата (\d\d\d?)
Будет пытаться захватить 3 цифры, если это возможно (RegExps жадные, чтобы они хватались как можно больше), но если он не может захватить 3 цифры, которые ?
делает третью цифру опциональной. Для просмотра (?=\d\d)
требуется, чтобы после первого захвата было по меньшей мере еще две цифры. Результатом этого является то, что если в строке осталось 5 или более цифр, это приведет к включению 3-х цифр в захват, но если осталось всего 4, это применит ?
чтобы захватить всего 2 цифры.
При выполнении нескольких совпадений с использованием флага g
строка используется от начала до конца за один проход. Каждый раз, когда он делает матч, он снова не возвращается к началу, он просто продолжается. Это означает, что совпадения никогда не могут перекрываться. Lookaheads дает возможность проверить, что будет дальше, не включая его в матче, чтобы вы могли эффективно перемотать назад.
Ключом к пониманию этого RegExp является наблюдение, что везде, где мы вставляем a -
в результате всегда должно быть как минимум еще 2 цифры после него. На английском языке он переводится как "захватить 3 цифры, если мы можем (или 2, если не можем), пока еще есть еще две цифры".
Здесь нерепрессивное решение:
joinGroups(joinDigits(partition3(extract(string))))
joinGroups
- это просто
// Join groups of digits with a hyphen.
const joinGroups = a => a.join('-');
joinDigits
достаточно просто:
// Join elements of subarrays together into strings.
const joinDigits = groups = groups.map(group => group.join(''));
extract
тоже легко:
// Extract all digits from a string and return as array.
const extract = input => input.match(/\d/g);
partition3
немного сложнее. Здесь много примеров на SO и в других местах. См. Реализацию в фрагменте для одной идеи.
const joinGroups = a => a.join('-');
const joinDigits = groups => groups.map(group => group.join(''));
const extract = input => input.match(/\d/g);
const partition = n =>
a => Array.from(
{length: Math.floor((a.length - 1) / n) + 1},
(_, i) => a.slice(i * n, (i + 1) * n));
const partition3 = partition(3);
const data = "00 64 33 3-44-23 982- 23-1-0";
console.log(joinGroups(joinDigits(partition3(extract(data)))));