I have a credit card # for amex I.E. 371449635398431 that I'd like to split up into 3 parts 3714 496353 98431 - Is there an easy way to split a string up by predefined indexes (in this case 4 & 10), possibly with a simple regex function?
4 Answers
I don't really see the need for regular expressions here. If you know the indexes you need to split on, you can just do this:
var input = '371449635398431'
var part1 = input.substr(0, 4);
var part2 = input.substr(4, 6);
var part3 = input.substr(10);
But if a regular expression is a must, you can do this:
var input = '371449635398431'
var match = /^(\d{4})(\d{6})(\d{5})$/.exec(input);
var part1 = match[1];
var part2 = match[2];
var part3 = match[3];
To insert spaces between each part you can do this:
var match = input.substr(0, 4) + ' ' + input.substr(4, 6) + ' ' + input.substr(10);
Or this:
var match = [ input.substr(0, 4), input.substr(4, 6), input.substr(10) ].join(' ');
Or this (inspired by Arun P Johny's answer):
var match = /^(\d{4})(\d{6})(\d{5})$/.exec(input).slice(1).join(' ');
Or this:
var match = input.replace(/^(\d{4})(\d{6})(\d{5})$/, '$1 $2 $3');
5 Comments
Corey
Is there any fallbacks to doing it the regex way? If the full amount of numbers are not listed, will it fail (as I see it looks for 4 then 6 then 5). Unfortunately I know very little about regex. How is it different having the ^ and $ in it compared to without? (Also: I was just trying to add spaces if the number is copy/pasted into the field and felt like it should be done on 1 line.)
Corey
Oh, also - is there any way to not grab the original full text? so I can just do a join(' ')? It seems a little redundant having to use the "splice(1)" as mentioned in Arun's answer.
p.s.w.g
The main problem is performance. Regex will be slower than direct manipulation.
^ and $ are start and end anchors, repsectively. It means that match will be an empty array if there are any leading / trailing characters. The regex will also return an empty array if there are not enough characters or if there are characters other than digits. Using match.splice(1).join(' ') (or slice(1)) is a good solution for this.beatgammit
@p.s.w.g - Performance is rarely a problem unless trying to build a game or something. I think simple, readable code is more important, unless the OP happens to be processing thousands of credit card numbers every second.
p.s.w.g
@tjameson Yes, very true. There's nothing wrong with any of these approaches (and someone could probably suggest another equally valid one). The regex solution is perfectly reasonable, but a lot of times I see regular expression used where direct string manipulation is more simple and readable. And of course, there's this.
Here I improve p.s.w.g answer by using slice instead substr (input string in s)
[s.slice(0,4), s.slice(4,10), s.slice(10)]
let s="371449635398431";
let a=[s.slice(0,4), s.slice(4,10), s.slice(10)]
console.log(a);
Comments
Below I simplified regex used in answers Arun P Johny and p.s.w.g
'371449635398431'.match(/(.{4})(.{6})(.{5})/).splice(1)
var a = '371449635398431'.match(/(.{4})(.{6})(.{5})/).splice(1);
console.log(a);