wper
wper

Reputation: 352

Separate string by numbers and characters

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

Answers (2)

Sifat Haque
Sifat Haque

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

CertainPerformance
CertainPerformance

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

Related Questions