Reputation: 352
I am trying to format a string to produce a new string in the correct format:
I have the following strings (left) which should be formatted to match (right):
[ 'xx9999', 'XX-99-99' ],
[ '9999xx', '99-99-XX' ],
[ '99xx99', '99-XX-99' ],
[ 'xx99xx', 'XX-99-XX' ],
[ 'xxxx99', 'XX-XX-99' ],
[ '99xxxx', '99-XX-XX' ],
[ '99xxx9', '99-XXX-9' ],
[ '9xxx99', '9-XXX-99' ],
[ 'xx999x', 'XX-999-X' ],
[ 'x999xx', 'X-999-XX' ],
[ 'xxx99x', 'XXX-99-X' ],
[ 'x99xxx', 'X-99-XXX' ],
[ '9xx999', '9-XX-999' ],
[ '999xx9', '999-XX-9' ]
I have tried the following but cannot get it to work correctly:
const formatLp = (userInput) => {
if (userInput) {
return userInput.toUpperCase().match(/[a-z]+|[^a-z]+/gi).join('-');
}
}
This works for some of them, such as 99xxx9
but not others such as xx9999
any help would be appreciated.
Upvotes: 0
Views: 264
Reputation: 6067
I've just implemented this using Stack
. Here is the function. You just need to pass the string to this function.
const convert = (str) => {
let stack = str.split('').reduce((newArr, char, index) => {
if(index !== 0 && newArr[newArr.length-1] !== char) {
newArr.push('-');
newArr.push(char);
return newArr;
} else {
newArr.push(char);
return newArr;
}
},[])
return stack.join('').toUpperCase();
}
// Here you can check this in action
const convert = (str) => {
let stack = str.split('').reduce((newArr, char, index) => {
if(index !== 0 && newArr[newArr.length-1] !== char) {
newArr.push('-');
newArr.push(char);
return newArr;
} else {
newArr.push(char);
return newArr;
}
},[])
return stack.join('').toUpperCase();
}
const strings = [ 'xx9999','9999xx','99xx99','xx99xx','xxxx99','99xxxx','99xxx9','9xxx99','xx999x','x999xx','xxx99x','x99xxx','9xx999','999xx9',];
strings.map(string => console.log(convert(string)))
Upvotes: 0
Reputation: 371203
Use .replace
twice - once to insert a -
between 4 repeated digits/non-digits, and once to insert a -
between digits and alphabetical characters:
const arr = [
[ 'xx9999', 'XX-99-99' ],
[ '9999xx', '99-99-XX' ],
[ '99xx99', '99-XX-99' ],
[ 'xx99xx', 'XX-99-XX' ],
[ 'xxxx99', 'XX-XX-99' ],
[ '99xxxx', '99-XX-XX' ],
[ '99xxx9', '99-XXX-9' ],
[ '9xxx99', '9-XXX-99' ],
[ 'xx999x', 'XX-999-X' ],
[ 'x999xx', 'X-999-XX' ],
[ 'xxx99x', 'XXX-99-X' ],
[ 'x99xxx', 'X-99-XXX' ],
[ '9xx999', '9-XX-999' ],
[ '999xx9', '999-XX-9' ]
];
arr.forEach(([str]) => {
const result = str.toUpperCase()
.replace(/\d{4}|\D{4}/, substr => `${substr.slice(0, 2)}-${substr.slice(2)}`)
.replace(/[a-z]{4}|\d(?=[a-z])|[a-z](?=\d)/gi, '$&-');
console.log(result);
});
You can also do it by matching and then joining - match 3 non-digits, or 3 digits, or 1-2 non-digits, or 1-2 digits:
const arr = [
[ 'xx9999', 'XX-99-99' ],
[ '9999xx', '99-99-XX' ],
[ '99xx99', '99-XX-99' ],
[ 'xx99xx', 'XX-99-XX' ],
[ 'xxxx99', 'XX-XX-99' ],
[ '99xxxx', '99-XX-XX' ],
[ '99xxx9', '99-XXX-9' ],
[ '9xxx99', '9-XXX-99' ],
[ 'xx999x', 'XX-999-X' ],
[ 'x999xx', 'X-999-XX' ],
[ 'xxx99x', 'XXX-99-X' ],
[ 'x99xxx', 'X-99-XXX' ],
[ '9xx999', '9-XX-999' ],
[ '999xx9', '999-XX-9' ]
];
arr.forEach(([str]) => {
const result = str.toUpperCase()
.match(/[a-z]{3}|\d{3}|[a-z]{1,2}|\d{1,2}/gi)
.join('-');
console.log(result);
});
Upvotes: 2