admin管理员组

文章数量:1317898

How would I go about reformating a string into blocks of 3 digits separated by dash (-) in JavaScript?

ex:

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

produce desired output as:

myString = "006-433-344-239-822-310"

How would I go about reformating a string into blocks of 3 digits separated by dash (-) in JavaScript?

ex:

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

produce desired output as:

myString = "006-433-344-239-822-310"
Share Improve this question edited Sep 15, 2017 at 3:56 Jonca33 asked Sep 15, 2017 at 2:02 Jonca33Jonca33 3,4937 gold badges28 silver badges39 bronze badges 1
  • Indeed @torazaburo. – Jonca33 Commented Sep 15, 2017 at 3:28
Add a ment  | 

4 Answers 4

Reset to default 7

With regex:

("00  64 33 3-44-23 982-  23-1-0").replace(/\D/g,"").replace(/(\d{3})(?!$)/g,'$1-')

Explanation:

  • \D - remove all non numeric characters

  • (\d{3})(?!$)

    • (\d{3}) - match 3 numbers
    • (?!$) - but not the last 3

To turn 0 - 22 1985--324 into 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'
  )

From what you've said in the ments I believe you want groups of 3 where possible and groups of 2 at the end if there aren't enough numbers. I believe this will do it:

[
    '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-'));
});

The /\D/g removes all the non-digits. The capture group (\d\d\d?) will attempt to grab 3 digits if it can (RegExps are greedy so they grab as much as possible) but if it can't grab 3 digits that ? makes the third digit optional. The lookahead (?=\d\d) requires there to be at least 2 more digits after the initial capture. The result of this is that if there are 5 or more digits remaining in the string this will result in 3 digits being included in the capture but if there are only 4 remaining it will apply the ? to grab just 2 digits.

When making multiple matches using the g flag the string is consumed from start to finish in one run. Each time it makes a match it doesn't go back to the start again, it just carries on. This means that matches can never overlap. Lookaheads provides a way to check what's ing up next without including it in the match, so that you can effectively rewind.

The key to understanding this RegExp is the observation that wherever we insert a - in the result there must always be at least 2 more digits after it. In English it translates as 'grab 3 digits if we can (or 2 if we can't) so long as there are 2 more digits yet to e'.

First you can use 'replace' to remove any non-digit characters with regex.

let myString = "00  64 33 3-44-23 982-  23-1-0"
myString = myString.replace(/\D/g, "")

// "006433344239822310"

Secondly, 'match' any digits (0-9) between 1 and 3 times. The match function conveniently returns an array with an item for each match.

myString = myString.match(/\d{1,3}/g)

// [006,433,344,239,822,310]

Lastly, join the array using "-" as the separator.

myString = myString.join("-");

// 006-433-344-239-822-310

And if you would like to chain each step together..

myString = myString.replace(/\D/g, "").match(/\d{1,3}/g).join("-");

Note that if the string has any leftover digits, they will be left in their own block on the end of the string. This is due to the 1-3 match.

For example..

"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

Here's a non-regexp solution:

joinGroups(joinDigits(partition3(extract(string))))

joinGroups is just

// Join groups of digits with a hyphen.
const joinGroups = a => a.join('-');

joinDigits is easy enough too:

// Join elements of subarrays together into strings.
const joinDigits = groups = groups.map(group => group.join(''));

extract is easy too:

// Extract all digits from a string and return as array.
const extract = input => input.match(/\d/g);

partition3 is a little harder. There are many samples here on SO and elsewhere. See the implementation in the snippet for one idea.

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

本文标签: javascriptFormat a string in blocks of 3 digitsStack Overflow