A Wizard Did It
A Wizard Did It

Reputation: 3674

How to convert "camelCase" to "Camel Case"?

I’ve been trying to get a JavaScript regex command to turn something like "thisString" into "This String" but the closest I’ve gotten is replacing a letter, resulting in something like "Thi String" or "This tring". Any ideas?

To clarify I can handle the simplicity of capitalizing a letter, I’m just not as strong with RegEx, and splitting "somethingLikeThis" into "something Like This" is where I’m having trouble.

Upvotes: 217

Views: 112557

Answers (13)

LEXYZ
LEXYZ

Reputation: 1

Here!

let str = "  55fromCamelHelveticaA10LTStdCASEVim77     ";
function fromCamelCase(str) {
    str = str.trim();
    let newStr = "";
    let prevItemIsUpperCase = false;
    const isUpperCase = (letter) => letter === letter.toUpperCase();
    const isLowerCase = (letter) => letter === letter.toLowerCase();
    const isNumber = (char) => /\d/.test(char);
    for (let index = 0; index < str.length; index++) {
        let item = str[index];
        let nextItem = index + 1 !== str.length ? str[index + 1] : false;
        if (isNumber(item)) {
            if (prevItemIsUpperCase) {
                newStr += " " + item;
            } else {
                newStr += item;
            }
            if (nextItem && !isNumber(nextItem) && isUpperCase(nextItem)) {
                newStr += " ";
            }
            prevItemIsUpperCase = false;
        }
        else if (isUpperCase(item)) {
            if (prevItemIsUpperCase && nextItem && isLowerCase(nextItem)) {
                newStr += " ";
            }
            newStr += item;
            prevItemIsUpperCase = true;
        }
        else if (isLowerCase(item)) {
            newStr += index ? item : item.toUpperCase();
            if (nextItem && isUpperCase(nextItem)) {
                newStr += " ";
            }
            prevItemIsUpperCase = false;
        }
    }
    return newStr;
}
console.log(fromCamelCase(str)); // "55from Camel Helvetica A 10 LT Std CASE Vim 77"

Upvotes: 0

SamGoody
SamGoody

Reputation: 14458

A solution that handles numbers as well:

function capSplit(str){
   return str.replace(
      /(^[a-z]+)|[0-9]+|[A-Z][a-z]+|[A-Z]+(?=[A-Z][a-z]|[0-9])/g,
      function(match, first){
          if (first) match = match[0].toUpperCase() + match.substr(1);
          return match + ' ';
          }
       )
   }

Tested here [JSFiddle, no library. Not tried IE]; should be pretty stable.

Upvotes: 7

kob003
kob003

Reputation: 3717

const value = 'camelCase';
const map = {};
let index = 0;
map[index] = [];
for (let i = 0; i < value.length; i++) {
  if (i !== 0 && value[i] === value[i].toUpperCase()) {
    index = i;
    map[index] = [];
  }
  if (i === 0) {
    map[index].push(value[i].toUpperCase());
  } else {
    map[index].push(value[i]);
  }
}
let resultArray = [];
Object.keys(map).map(function (key, index) {
  resultArray = [...resultArray, ' ', ...map[key]];
  return resultArray;
});
console.log(resultArray.join(''));

Upvotes: 0

Vincent Robert
Vincent Robert

Reputation: 36120

"thisStringIsGood"
    // insert a space before all caps
    .replace(/([A-Z])/g, ' $1')
    // uppercase the first character
    .replace(/^./, function(str){ return str.toUpperCase(); })

displays

This String Is Good

(function() {

  const textbox = document.querySelector('#textbox')
  const result = document.querySelector('#result')
  function split() {
      result.innerText = textbox.value
        // insert a space before all caps
        .replace(/([A-Z])/g, ' $1')
        // uppercase the first character
        .replace(/^./, (str) => str.toUpperCase())
    };

  textbox.addEventListener('input', split);
  split();
}());
#result {
  margin-top: 1em;
  padding: .5em;
  background: #eee;
  white-space: pre;
}
<div>
  Text to split
  <input id="textbox" value="thisStringIsGood" />
</div>

<div id="result"></div>

Upvotes: 480

rob
rob

Reputation: 10119

Not regex, but useful to know plain and old techniques like this:

var origString = "thisString";
var newString = origString.charAt(0).toUpperCase() + origString.substring(1);

Upvotes: -7

M3ghana
M3ghana

Reputation: 1271

Try this solution here -

var value = "myCamelCaseText";
var newStr = '';
for (var i = 0; i < value.length; i++) {
  if (value.charAt(i) === value.charAt(i).toUpperCase()) {
    newStr = newStr + ' ' + value.charAt(i)
  } else {
    (i == 0) ? (newStr += value.charAt(i).toUpperCase()) : (newStr += value.charAt(i));
  }
}
return newStr;

Upvotes: 2

pykiss
pykiss

Reputation: 1077

My version

function camelToSpace (txt) {
  return txt
    .replace(/([^A-Z]*)([A-Z]*)([A-Z])([^A-Z]*)/g, '$1 $2 $3$4')
    .replace(/ +/g, ' ')
}
camelToSpace("camelToSpaceWithTLAStuff") //=> "camel To Space With TLA Stuff"

Upvotes: 0

Lawrence Chang
Lawrence Chang

Reputation: 449

Lodash handles this nicely with _.startCase()

Upvotes: 19

thegreenpizza
thegreenpizza

Reputation: 1451

I think this should be able to handle consecutive uppercase characters as well as simple camelCase.

For example: someVariable => someVariable, but ABCCode != A B C Code.

The below regex works on your example but also the common example of representing abbreviations in camcelCase.

"somethingLikeThis"
    .replace(/([a-z])([A-Z])/g, '$1 $2')
    .replace(/([A-Z])([a-z])/g, ' $1$2')
    .replace(/\ +/g, ' ') => "something Like This"

"someVariableWithABCCode"
    .replace(/([a-z])([A-Z])/g, '$1 $2')
    .replace(/([A-Z])([a-z])/g, ' $1$2')
    .replace(/\ +/g, ' ') => "some Variable With ABC Code"

You could also adjust as above to capitalize the first character.

Upvotes: 22

If you don't care about older browsers (or don't mind using a fallback reduce function for them), this can split even strings like 'xmlHTTPRequest' (but certainly the likes of 'XMLHTTPRequest' cannot).

function splitCamelCase(str) {
        return str.split(/(?=[A-Z])/)
                  .reduce(function(p, c, i) {
                    if (c.length === 1) {
                        if (i === 0) {
                            p.push(c);
                        } else {
                            var last = p.pop(), ending = last.slice(-1);
                            if (ending === ending.toLowerCase()) {
                                p.push(last);
                                p.push(c);
                            } else {
                                p.push(last + c);
                            }
                        }
                    } else {
                        p.push(c.charAt(0).toUpperCase() + c.slice(1));
                    }
                    return p;
                  }, [])
                  .join(' ');
}

Upvotes: 0

Matt Wiebe
Matt Wiebe

Reputation: 1091

I had an idle interest in this, particularly in handling sequences of capitals, such as in xmlHTTPRequest. The listed functions would produce "Xml H T T P Request" or "Xml HTTPRequest", mine produces "Xml HTTP Request".

function unCamelCase (str){
    return str
        // insert a space between lower & upper
        .replace(/([a-z])([A-Z])/g, '$1 $2')
        // space before last upper in a sequence followed by lower
        .replace(/\b([A-Z]+)([A-Z])([a-z])/, '$1 $2$3')
        // uppercase the first character
        .replace(/^./, function(str){ return str.toUpperCase(); })
}

There's also a String.prototype version in a gist.

Upvotes: 99

PleaseStand
PleaseStand

Reputation: 32052

This can be concisely done with regex lookahead (live demo):

function splitCamelCaseToString(s) {
    return s.split(/(?=[A-Z])/).join(' ');
}

(I thought that the g (global) flag was necessary, but oddly enough, it isn't in this particular case.)

Using lookahead with split ensures that the matched capital letter is not consumed and avoids dealing with a leading space if UpperCamelCase is something you need to deal with. To capitalize the first letter of each, you can use:

function splitCamelCaseToString(s) {
    return s.split(/(?=[A-Z])/).map(function(p) {
        return p.charAt(0).toUpperCase() + p.slice(1);
    }).join(' ');
}

The map array method is an ES5 feature, but you can still use it in older browsers with some code from MDC. Alternatively, you can iterate over the array elements using a for loop.

Upvotes: 28

kennebec
kennebec

Reputation: 104760

function spacecamel(s){
    return s.replace(/([a-z])([A-Z])/g, '$1 $2');
}

spacecamel('somethingLikeThis')

// returned value: something Like This

Upvotes: 14

Related Questions