Reputation: 2620
I have camel cased strings like this:
"numberOf40"
"numberOf40hc"
How can I split it like this?
["number", "Of", "40"]
["number", "Of", "40hc"]
I am using humps to decamelize keys so I can only pass a split
regex as option. I am looking for an answer that only uses split
function.
My best attempts:
const a = "numberOf40hc"
a.split(/(?=[A-Z0-9])/)
// ["number", "Of", "4", "0hc"]
a.split(/(?=[A-Z])|[^0-9](?=[0-9])/)
// ["number", "O", "40hc"]
Also I don't understand why the f
is omitted in my last attempt.
Upvotes: 2
Views: 1310
Reputation: 163362
You don't get the f
in you last attempt (?=[A-Z])|[^0-9](?=[0-9])
as this part of the last pattern [^0-9]
matches a single char other than a digit and will split on that char.
You could also match instead of split
const regex = /[A-Z]?[a-z]+|\d+[a-z]*/g;
[
"numberOf40",
"numberOf40hc"
].forEach(s => console.log(Array.from(s.matchAll(regex), m => m[0])));
Using split only, you could use lookarounds with a lookbehind which is gaining more browser support.
const regex = /(?=[A-Z])|(?<=[a-z])(?=\d)/g;
[
"numberOf40",
"numberOf40hc"
].forEach(s => console.log(s.split(regex)));
Upvotes: 3
Reputation: 11584
const a = "numberOf40hc"
let b = a.split(/(\d+[a-z]*|[A-Z][a-z]*)/).filter(a => a);
console.log(b);
The .filter(a => a)
is necessary because split
, returns both the left and right side of a matched delimter. E.g. 'a.'.split('.')
returns both the left (i.e. 'a'
) and right (i.e. ''
) side of '.'
.
Per your update regarding the need for compatibility with humps
, it seems humps
supports customizing the handler:
const humps = require('humps');
let myObj = {numberOf40hc: 'value'};
let decamelizedObj = humps.decamelizeKeys(myObj, key =>
key.split(/(\d+[a-z]*|[A-Z][a-z]*)/).filter(a => a).join('_'));
console.log(decamelizedObj);
Upvotes: 2
Reputation: 28414
Try this:
const splitStr = (str='') =>
str.split(/([A-Z][a-z]+)/).filter(e => e);
console.log( splitStr("numberOf40") );
console.log( splitStr("numberOf40hc") );
Upvotes: 1