adesurirey
adesurirey

Reputation: 2620

How to split a camel case string containing numbers

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

Answers (3)

The fourth bird
The fourth bird

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

junvar
junvar

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

Majed Badawi
Majed Badawi

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

Related Questions