# Simpler version of capitalizing each word in a string

I have this code which does the job, however it seems to me that the same could be done with less code. And why if I put 'var newString = stored.join(' ');' below 'var stored=[];' the code doesn't work?

function titleCase(str) {

var lower = str.toLowerCase();

var arr = lower.split(' ');

var stored = [];

//takes a string from arr
for(var i = 0; i<arr.length; i++) {

//splits and stores the string to letters
var word = arr[i].split(''); // ['l','i','t'...]

// takes the first letter from the array and makes it uppercase
for(var k=0; k<1; k++){
var upper = word[k].toUpperCase();
word.shift();
word.unshift(upper);
var joined = word.join('');
stored.push(joined);
}

}
var newString = stored.join(' ');

return newString;

}

titleCase("I'm a little tea pot");


## migrated from stackoverflow.comAug 12 '17 at 21:06

This question came from our site for professional and enthusiast programmers.

• What would be the output of titleCase("I'm a little tea pot");? – Yagna Patel Aug 12 '17 at 19:13
• You mean it doesn't work when you move the var newString = stored.join(' '); above the loop? Well obviously that's because the array isn't yet filled. – Bergi Aug 12 '17 at 19:13

You can use String#replace with a regexp:

function titleCase(str) {
return str.toLowerCase() // change the string to lowercase
.replace(/\S+/g, function(s) { // get all non space characters sequences
return s.charAt(0).toUpperCase() + s.substring(1); // uppercase the 1st letter and combine with the rest of the string
});
}

console.log(titleCase("I'm a little tea pot"));

You can split the string by space, then use map function to iterate over words and uppercase each word and then join it back again:

"I'm a little tea pot"
.split(' ')
.map(function(word) {
return word[0].toUpperCase() + word.substring(1);
})
.join(' ');

• huh...so the argument 'word' in the function is the current value being procesed? And by 'word[0]' it takes the first letter of the word? I thought that you have to use '[ ]' only on an array. Or that value being processed becomes an array somehow? Sorry for dumb questions... – Benas Lengvinas Aug 12 '17 at 20:50

A more succinct string replace variant:

   str.replace (/(^|\s)\S/g, match => match.toUpperCase () );


The regexp matches the satrt of string or a space followed by a non-space character. The entrire match is up-cased and returned.

• Consider using \b instead of (^|\s). Not only is it simpler, it also has the advantage of working with words that follow punctuation (such as a double-quote). – 200_success Sep 9 '17 at 7:31

I would use the regex /([^ ]+)/g to match for each word and then change the first letter.

var titleCase = (text) => text.replace(/([^ ]+)/g, (w) => w[0].toUpperCase() + w.substring(1));

console.log(titleCase("I'm a little tea pot"));

Instead of providing a complete solution like the other answers (migrated from SO), I'll point out a few specific things that could be improved:

//splits and stores the string to letters
var word = arr[i].split(''); // ['l','i','t'...]


That's not really necessary. You can used indexed access, a length property and the same iteration on the string itself.

// takes the first letter from the array and makes it uppercase
for(var k=0; k<1; k++){
var upper = word[k].toUpperCase();


Why is this a loop? It loops exactly once, testing whether 0 < 1. Just drop that and place

var upper = word[0].toUpperCase();

word.shift();
word.unshift(upper);


Don't do that. It move the whole array around and then back. Just assign to the first index:

word[0] = upper;

var joined = word.join('');


If we didn't split the arr[i] word in the word array, we could instead use

var joined = arr[i][0].toUpperCase() // upper
+ arr[i].slice(1); // the rest of the string

var stored = [];
//takes a string from arr
for(var i = 0; i<arr.length; i++) {
…
stored.push(joined);
}


Instead of filling that stored array, you could have mutated the original one (for a tiny bit of better performance). But creating a new array is fine.

However, when creating a new array with one item per item from the original array, the map method helps a lot to remove the boilerplate loop, array instantiation and pushing.

var lower = str.toLowerCase();
var arr = lower.split(' ');
…
var newString = stored.join(' ');
return newString;


Since you specifically asked about doing it with less code: use less variables. If you only use a variable exactly once, the expression might as well be inlined:

var arr = str.toLowerCase().split(' ');
…
return stored.join(' ');


It's often beneficial for clarity to use more of such descriptive variable names, but it also is a lot longer.

If you apply all these points, you'll basically end up with madox2's solution.

I would change the regex to only match the first character in a word instead of using a concatenation like others did:

function titleCase(str) {
return str.replace(/(^|\s)\w/g, (s) => s.toUpperCase() );
}

console.log(titleCase("I'm a little tea pot"));

However there are some questions you might want to consider. For example a newspaper would not capitalize a (or an or the) and hyphenated words are (High-Quality) are sometimes capitalized.

• Use [a-z] instead of \w. \w = [a-zA-Z0-9_]. – Tushar May 8 at 3:28