1

Basically I want to do this:

I get a string "myVariableName" and turn it into: ["my", "variable", "name"]

I tried doing this using regex, but I get a lot of undefineds in my ending array it seems. The two possible cases for variable names are camel-case and upper snake-case in this situation.

const matchVariableNames =  /(\b[a-z]+)|([A-Z][a-z]+)|(\b[A-Z]+)|(_[A-Z]+)/g;
const variableName = 'myVariable';
let words = [];
let regexMatches;

while (regexMatches = matchVariableNames.exec(variableName)) {
  regexMatches.forEach((match) => {
    words.push(match);
  }); 
};

outputs:

["my", "my", undefined, undefined, undefined, "Variable", undefined, "Variable", undefined, undefined]
undefined
mplungjan
  • 169,008
  • 28
  • 173
  • 236
Shayan Javadi
  • 293
  • 3
  • 20
  • `"myVariableName".match(/((?:^|[A-Z])[a-z]+)/g)` technically some non-alpha chars are acceptable as var names but this might suffice depending on your var naming convention – CrayonViolent Jun 06 '17 at 14:47
  • Or a better duplicate: https://stackoverflow.com/questions/13720256/javascript-regex-camelcase-to-sentence – mplungjan Jun 06 '17 at 14:49
  • `console.log( "myVariableName" .replace(/^[a-z]|[A-Z]/g, function(v, i) { return (i === 0 ? "":" ")+ v.toLowerCase(); }).split(" ") ) ` – mplungjan Jun 06 '17 at 15:32

3 Answers3

3

You could use a positive lookahead with uppercase letters. Then map only lower case letters.

var string = 'myVariableName',
    array = string.split(/(?=[A-Z])/).map(a => a.toLowerCase());
    
console.log(array);
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
2

I don't think a regular expression is a good fit for this. (I don't accept Regular expression to identify CamelCased words with leading uppercase letter as a duplicate since the question does not ask for a regular expression persé).

The way I read it you want to parse words written in camelcase. Immediately I imagine special cases such as "DOMElement and "PDFParser". I would expect the output to be [ "DOM", "Element" ] and [ "PDF", "Parser" ]. I think we can write a function that works like that.

function parseWordsFromCamelCaseString(string) {
  var i, words, last_word_char, last_case, current_case;
  words = [];
  last_word_start = 0;
  last_case = null; // false=lower, true=upper

  for (i = 0; i < string.length; i += 1) {
    current_case = string[i].toUpperCase() === string[i];
    if (last_case !== null && current_case !== last_case) {
      if (current_case === true) { // lowercase to uppercase transition
        words.push(string.substring(last_word_start, i));
        last_word_start = i;
      } else { // uppercase to lowercase transition
        if (last_word_start < i - 1) {
          words.push(string.substring(last_word_start, i - 1));
        }
        last_word_start = i - 1;
      }
    }
    last_case = current_case;
  }
  if (last_word_start < i - 1) {
    words.push(string.substring(last_word_start, i));
  }
  return words;
}

console.log(parseWordsFromCamelCaseString("fooBar"));
console.log(parseWordsFromCamelCaseString("parseWordsFromCamelCaseString"));
console.log(parseWordsFromCamelCaseString("DOMElement"));
console.log(parseWordsFromCamelCaseString("fooDOMElement"));

Output

["foo", "Bar"]
["parse", "Words", "From", "Camel", "Case", "String"]
["DOM", "Element"]
["foo", "DOM", "Element"]

It also works for "foo" (no case transition) and "" (empty string).

mplungjan
  • 169,008
  • 28
  • 173
  • 236
Halcyon
  • 57,230
  • 10
  • 89
  • 128
  • Do you recognise [javascript-regex-camelcase-to-sentence](https://stackoverflow.com/questions/13720256/javascript-regex-camelcase-to-sentence) as a duplicate then? – mplungjan Jun 06 '17 at 15:34
  • @mplungjan I don't see why. There are no non-regular expression answers. And none of them correctly handle the (not so-)special case that I outlined. – Halcyon Jun 06 '17 at 15:35
-1

I've created this:

x = 'myVariableName';
const isUpper = e => (e === e.toUpperCase());
[].reduce.call(x, (words, letter, i) => {
  if(isUpper(letter)) words.push([letter]);
  else {
    let length = words.length-1,
        word = words[length];
    words[length] = word+letter;
  }
  return words;
}, [[]]);

Returns ["my", "Variable", "Name"]

Is it very elegant? We can fight about it, but I'm sure more than your RegExp. :P

Reski
  • 169
  • 7
  • It breaks on input like `"myPDFFile"`. It returns `[ "my", [ "p" ], [ "D" ], [ "F" ], "File" ]` – Halcyon Jun 06 '17 at 15:13