Формат строки в блоках по 3 цифры

1

Как мне переделать строку в блоки из 3-х цифр, разделенных тире (-) в JavaScript?

например:

let myString = "00  64 33 3-44-23 982-  23-1-0"

выдать желаемый результат:

myString = "006-433-344-239-822-310"
  • 0
    Действительно @torazaburo.
Теги:
string

4 ответа

6
Лучший ответ

С регулярным выражением:

("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'
  )
  • 0
    Спасибо, Исаак. Regex - это новая территория для меня. Что будет эквивалентным регулярным выражением для следующего: 0 - 22 1985--324, что приведет к 022-198-53-24. Нужно ли сравнивать строку с% 3?
  • 0
    Я бы сделал что-то другое для этого, но для этого точного формата я исправлю свой ответ
Показать ещё 1 комментарий
3

Сначала вы можете использовать "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
2

Из того, что вы сказали в комментариях, я считаю, что вам нужны группы из 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, если не можем), пока еще есть еще две цифры".

  • 0
    Это точно верно. Большое спасибо @Skirtle. Я потрачу некоторое время на изучение вашего решения. Я принял ответ Исаака, поэтому у меня не будет проблем с модераторами, помечающими мой первоначальный вопрос. Еще раз спасибо!
  • 0
    @ tonkihonks13 Не проблема, решение Исаака хорошо работает для первоначального вопроса. Я был в раздумье о том, стоит ли публиковать свое решение в качестве комментария к его решению. В конце концов я решил, что мне нужен собственный ответ, чтобы включить объяснение.
1

Здесь нерепрессивное решение:

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)))));

Ещё вопросы

Сообщество Overcoder
Наверх
Меню