Reputation: 14168
Why does this fail? Should I (somehow) escape letter i
— this doesn't fail with other characters.
titleCase("I'm a little tea pot");
// Prints: "i'm A Little Tea Pot"
// Expected: "I'm A Little Tea Pot"
function titleCase(str) {
return str.split(' ').map(function(each) {
return each.toLowerCase().replace(each[0], each[0].toUpperCase());
}).join(' ');
}
Upvotes: 3
Views: 255
Reputation: 12422
toLowerCase
returns a new string, it does not update the value of each
. So when "I'm"
is assigned to each
what you are effectively getting is:
"i'm".replace("I", "I".toUpperCase());
"I"
is not in the string "i'm"
, so nothing is replaced.
Instead of splitting the string, running replace on each token and joining it, I would instead do it with a single replace
with RegExp and a replacement function:
function titleCase (str) {
var upper = function (wholeMatch, before, firstLetter) {
return before + firstLetter.toUpperCase();
};
return (str.toLowerCase()).replace(/(^\s*|\s+)(.)/g, upper);
}
titleCase("I'm a little tEa pot");
// "I'm A Little Tea Pot"
titleCase(" I'm a little tEa pot");
// " I'm A Little Tea Pot"
titleCase(" I'm a little tEa pot");
" I'm A Little Tea Pot"
/(^\s*|\s+)(.)/g
finds either the start of the string (with optional white-space) or white-space followed by any single character. The upper
function then uppercases the character and returns any captured white-space and that upper case character to act as the replacement.
Upvotes: 0
Reputation: 1653
Run the following snippet and look at the output.
var each ="I'm";
console.log(`Change ${each[0]} to ${each[0].toUpperCase()} in ${each.toLowerCase()}`);
console.log('Result:', each.toLowerCase().replace(each[0], each[0].toUpperCase()));
You should see that the char to search is a capital "I" but the first char in the string is a lower case "i".
function titleCase(str) {
return str.toLowerCase().split(' ').map(function(each) {
return each.replace(each[0], each[0].toUpperCase());
}).join(' ');
}
console.log(titleCase("I\'m a little tea pot"));
// Prints: "i'm A Little Tea Pot"
// Expected: "I'm A Little Tea Pot"
Upvotes: 1
Reputation: 5246
For "I'm" part of string the uppercase "I" converted to lowercase "i" and trying to replace the lowercase "i" with uppercase 'I' which is not even exist in the string.
So modified your function in the beginning converted entire string in lowercase.
Please check below working snippet.
console.log(titleCase("I'm a little tea pot"));
// Prints: "i'm A Little Tea Pot"
// Expected: "I'm A Little Tea Pot"
function titleCase(str) {
str = str.toLowerCase();
return str.split(' ').map(function(each) {
//console.log(each[0].toUpperCase());
return each.toLowerCase().replace(each[0], each[0].toUpperCase());
}).join(' ');
}
Upvotes: 1
Reputation: 419
You can also use regular expression for this.
function titleCase(str) {
return str.replace(/(?:^|\s)\w/g, function(match) {
return match.toUpperCase();
});
}
Upvotes: 0
Reputation: 38456
The .toLowerCase()
is happening on the original value of each
, so the .replace()
may/will not give you the expected results.
If you split it out as a separate statement, it should work as expected:
function titleCase(str) {
return str.split(' ').map(function(each) {
each = each.toLowerCase();
return each.replace(each[0], each[0].toUpperCase());
}).join(' ');
}
As a slightly more efficient approach, it would also be better to move the .toLowerCase()
to before the .map()
call so it only needs to be called once, instead of once-per-word:
function titleCase(str) {
str = str.toLowerCase();
return str.split(' ').map(function(each) {
return each.replace(each[0], each[0].toUpperCase());
}).join(' ');
}
Upvotes: 3
Reputation: 24945
You can try something like this:
function titleCase(str) {
return str.split(' ').map(function(each) {
return each.charAt(0).toUpperCase() + each.substring(1).toLowerCase();
}).join(' ');
}
console.log(titleCase("I'm a little tea pot"));
function titleCase(str) {
return str.split(' ').reduce(function(p,c) {
return p + " " + toTitle(c);
});
}
function toTitle(str){
return str.charAt(0).toUpperCase() + str.substring(1).toLowerCase();
}
console.log(titleCase("I'm a little tea pot"));
Upvotes: 1
Reputation: 68413
It is simple.
replace(each[0], each[0].toUpperCase());
will only replace lowerCase
items, and I
is not lowercase
since each[0]
being not yet replaced.
For other words in the sentence, their first character is lowercase, so they stay lowercase after lowercase()
is called on each
.
Upvotes: 0