admin管理员组文章数量:1125572
Is there a simple way to convert a string to Title Case? E.g. john smith
becomes John Smith
. I'm not looking for something complicated like John Resig's solution, just (hopefully) some kind of one- or two-liner.
Is there a simple way to convert a string to Title Case? E.g. john smith
becomes John Smith
. I'm not looking for something complicated like John Resig's solution, just (hopefully) some kind of one- or two-liner.
- 1 There are various methods, do we have some performance stats? – theAnubhav Commented Oct 2, 2016 at 12:18
- 1 @theAnubhav yes we do have a benchmark now – Ulysse BN Commented Nov 19, 2020 at 10:57
- 3 It's the year 2022, and browsers still do not have a native function to do this. – Sơn Trần-Nguyễn Commented Jun 30, 2022 at 3:23
- 1 Casing like this is 100% language/location/culture dependent. – James Moore Commented Aug 10, 2022 at 20:54
- 1 I want one of the test cases for the solution to be "Comhrá i mBÁC le Seán Nguyen" - good luck with that one! Basically, the idea that there's something called "title casing" that a computer can do is probably hopeless, even given vast amounts of machine-learning resources. – James Moore Commented Aug 10, 2022 at 21:11
70 Answers
Reset to default 1 2 3 Next 1006Use:
function toTitleCase(str) {
return str.replace(
/\w\S*/g,
text => text.charAt(0).toUpperCase() + text.substring(1).toLowerCase()
);
}
const example = 'john smith';
console.log(`"${example}" becomes "${toTitleCase(example)}"`);
Interactive example:
const input = document.querySelector('[name="input"]');
const output = document.querySelector('[name="output"]');
input.addEventListener('change', () => {
output.value = toTitleCase(input.value);
});
input.addEventListener('keyup', () => {
output.value = toTitleCase(input.value);
});
output.addEventListener('click', () => output.select());
function toTitleCase(str) {
return str.replace(
/\w\S*/g,
text => text.charAt(0).toUpperCase() + text.substring(1).toLowerCase()
);
}
<form>
Input: <br/>
<textarea name="input"></textarea>
<br/>
Output: <br/>
<textarea name="output" readonly></textarea>
</form>
If a CSS solution meets your needs, you can apply the text-transform CSS style to your controls:
text-transform: capitalize;
Just be aware that this will transform:
hello world
to Hello World
HELLO WORLD
to HELLO WORLD
(no change)
emily-jane o'brien
to Emily-jane O'brien
(incorrect)
Maria von Trapp
to Maria Von Trapp
(incorrect)
A slightly more elegant way, adapting Greg Dean's function:
String.prototype.toProperCase = function () {
return this.replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();});
};
Call it like:
"pascal".toProperCase();
Here's my version, IMO it's easy to understand and elegant too.
const str = "foo bar baz";
const newStr = str.split(' ')
.map(w => w[0].toUpperCase() + w.substring(1).toLowerCase())
.join(' ');
console.log(newStr);
Here’s my function that converts to title case but also preserves defined acronyms as uppercase and minor words as lowercase:
String.prototype.toTitleCase = function() {
var i, j, str, lowers, uppers;
str = this.replace(/([^\W_]+[^\s-]*) */g, function(txt) {
return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
});
// Certain minor words should be left lowercase unless
// they are the first or last words in the string
lowers = ['A', 'An', 'The', 'And', 'But', 'Or', 'For', 'Nor', 'As', 'At',
'By', 'For', 'From', 'In', 'Into', 'Near', 'Of', 'On', 'Onto', 'To', 'With'];
for (i = 0, j = lowers.length; i < j; i++)
str = str.replace(new RegExp('\\s' + lowers[i] + '\\s', 'g'),
function(txt) {
return txt.toLowerCase();
});
// Certain words such as initialisms or acronyms should be left uppercase
uppers = ['Id', 'Tv'];
for (i = 0, j = uppers.length; i < j; i++)
str = str.replace(new RegExp('\\b' + uppers[i] + '\\b', 'g'),
uppers[i].toUpperCase());
return str;
}
For example:
"TO LOGIN TO THIS SITE and watch tv, please enter a valid id:".toTitleCase();
// Returns: "To Login to This Site and Watch TV, Please Enter a Valid ID:"
You could immediately toLowerCase
the string, and then just toUpperCase
the first letter of each word. Becomes a very simple 1 liner:
function titleCase(str) {
return str.toLowerCase().replace(/\b\w/g, s => s.toUpperCase());
}
console.log(titleCase('iron man'));
console.log(titleCase('iNcrEdible hulK'));
I prefer the following over the other answers. It matches only the first letter of each word and capitalises it. Simpler code, easier to read and less bytes. It preserves existing capital letters to prevent distorting acronyms. However you can always call toLowerCase()
on your string first.
function title(str) {
return str.replace(/(^|\s)\S/g, function(t) { return t.toUpperCase() });
}
You can add this to your string prototype which will allow you to 'my string'.toTitle()
as follows:
String.prototype.toTitle = function() {
return this.replace(/(^|\s)\S/g, function(t) { return t.toUpperCase() });
}
Example:
String.prototype.toTitle = function() {
return this.replace(/(^|\s)\S/g, function(t) { return t.toUpperCase() });
}
console.log('all lower case ->','all lower case'.toTitle());
console.log('ALL UPPER CASE ->','ALL UPPER CASE'.toTitle());
console.log("I'm a little teapot ->","I'm a little teapot".toTitle());
Benchmark
TL;DR
The winner of this benchmark is the plain old for loop:
function titleize(str) {
let upper = true
let newStr = ""
for (let i = 0, l = str.length; i < l; i++) {
// Note that you can also check for all kinds of spaces with
// str[i].match(/\s/)
if (str[i] == " ") {
upper = true
newStr += str[i]
continue
}
newStr += upper ? str[i].toUpperCase() : str[i].toLowerCase()
upper = false
}
return newStr
}
// NOTE: you could beat that using charcode and string builder I guess.
Details
I've taken the most popular and distinct answers and made a benchmark with those.
Here's the result on my MacBook pro:
And for completeness, here are the functions used:
str = "the QUICK BrOWn Fox jUMPS oVeR the LAzy doG";
function regex(str) {
return str.replace(
/\w\S*/g,
function(txt) {
return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
}
);
}
function split(str) {
return str.
split(' ').
map(w => w[0].toUpperCase() + w.substr(1).toLowerCase()).
join(' ');
}
function complete(str) {
var i, j, str, lowers, uppers;
str = str.replace(/([^\W_]+[^\s-]*) */g, function(txt) {
return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
});
// Certain minor words should be left lowercase unless
// they are the first or last words in the string
lowers = ['A', 'An', 'The', 'And', 'But', 'Or', 'For', 'Nor', 'As', 'At',
'By', 'For', 'From', 'In', 'Into', 'Near', 'Of', 'On', 'Onto', 'To', 'With'];
for (i = 0, j = lowers.length; i < j; i++)
str = str.replace(new RegExp('\\s' + lowers[i] + '\\s', 'g'),
function(txt) {
return txt.toLowerCase();
});
// Certain words such as initialisms or acronyms should be left uppercase
uppers = ['Id', 'Tv'];
for (i = 0, j = uppers.length; i < j; i++)
str = str.replace(new RegExp('\\b' + uppers[i] + '\\b', 'g'),
uppers[i].toUpperCase());
return str;
}
function firstLetterOnly(str) {
return str.replace(/\b(\S)/g, function(t) { return t.toUpperCase(); });
}
function forLoop(str) {
let upper = true;
let newStr = "";
for (let i = 0, l = str.length; i < l; i++) {
if (str[i] == " ") {
upper = true;
newStr += " ";
continue;
}
newStr += upper ? str[i].toUpperCase() : str[i].toLowerCase();
upper = false;
}
return newStr;
}
Note that i deliberately did not change the prototype since I consider it a really bad practice and I don't think we should promote such practice in our answers. This is only ok for small codebases when you're the only one working on it.
If you want to add any other way to do it to this benchmark, please comment a link to the answer !
EDIT 2022 Mac M1: On my new computer, with more recent chrome, split wins. If you really care about performance on a specific machine you should run the benchmark yourself
var result =
'this is very interesting'.replace(/\b[a-z]/g, (x) => x.toUpperCase())
console.log(result) // This Is Very Interesting
Surprised to see no one mentioned the use of rest parameter. Here is a simple one liner that uses ES6 Rest parameters.
let str="john smith"
str=str.split(" ").map(([firstChar,...rest])=>firstChar.toUpperCase()+rest.join("").toLowerCase()).join(" ")
console.log(str)
Without using regex just for reference:
String.prototype.toProperCase = function() {
var words = this.split(' ');
var results = [];
for (var i = 0; i < words.length; i++) {
var letter = words[i].charAt(0).toUpperCase();
results.push(letter + words[i].slice(1));
}
return results.join(' ');
};
console.log(
'john smith'.toProperCase()
)
Just in case you are worried about those filler words, you can always just tell the function what not to capitalize.
/**
* @param String str The text to be converted to titleCase.
* @param Array glue the words to leave in lowercase.
*/
var titleCase = function(str, glue){
glue = (glue) ? glue : ['of', 'for', 'and'];
return str.replace(/(\w)(\w*)/g, function(_, i, r){
var j = i.toUpperCase() + (r != null ? r : "");
return (glue.indexOf(j.toLowerCase())<0)?j:j.toLowerCase();
});
};
Hope this helps you out.
edit
If you want to handle leading glue words, you can keep track of this w/ one more variable:
var titleCase = function(str, glue){
glue = !!glue ? glue : ['of', 'for', 'and', 'a'];
var first = true;
return str.replace(/(\w)(\w*)/g, function(_, i, r) {
var j = i.toUpperCase() + (r != null ? r : '').toLowerCase();
var result = ((glue.indexOf(j.toLowerCase()) < 0) || first) ? j : j.toLowerCase();
first = false;
return result;
});
};
If you need a grammatically correct answer:
This answer takes into account prepositions such as "of", "from", .. The output will generate an editorial style title you would expect to see in a paper.
toTitleCase Function
The function that takes into account grammar rules listed here. The function also consolidates whitespace and removes special characters (modify regex for your needs)
const toTitleCase = (str) => {
const articles = ['a', 'an', 'the'];
const conjunctions = ['for', 'and', 'nor', 'but', 'or', 'yet', 'so'];
const prepositions = [
'with', 'at', 'from', 'into','upon', 'of', 'to', 'in', 'for',
'on', 'by', 'like', 'over', 'plus', 'but', 'up', 'down', 'off', 'near'
];
// The list of spacial characters can be tweaked here
const replaceCharsWithSpace = (str) => str.replace(/[^0-9a-z&/\\]/gi, ' ').replace(/(\s\s+)/gi, ' ');
const capitalizeFirstLetter = (str) => str.charAt(0).toUpperCase() + str.substr(1);
const normalizeStr = (str) => str.toLowerCase().trim();
const shouldCapitalize = (word, fullWordList, posWithinStr) => {
if ((posWithinStr == 0) || (posWithinStr == fullWordList.length - 1)) {
return true;
}
return !(articles.includes(word) || conjunctions.includes(word) || prepositions.includes(word));
}
str = replaceCharsWithSpace(str);
str = normalizeStr(str);
let words = str.split(' ');
if (words.length <= 2) { // Strings less than 3 words long should always have first words capitalized
words = words.map(w => capitalizeFirstLetter(w));
}
else {
for (let i = 0; i < words.length; i++) {
words[i] = (shouldCapitalize(words[i], words, i) ? capitalizeFirstLetter(words[i], words, i) : words[i]);
}
}
return words.join(' ');
}
Unit Tests to Ensure Correctness
import { expect } from 'chai';
import { toTitleCase } from '../../src/lib/stringHelper';
describe('toTitleCase', () => {
it('Capitalizes first letter of each word irrespective of articles, conjunctions or prepositions if string is no greater than two words long', function(){
expect(toTitleCase('the dog')).to.equal('The Dog'); // Capitalize articles when only two words long
expect(toTitleCase('for all')).to.equal('For All'); // Capitalize conjunctions when only two words long
expect(toTitleCase('with cats')).to.equal('With Cats'); // Capitalize prepositions when only two words long
});
it('Always capitalize first and last words in a string irrespective of articles, conjunctions or prepositions', function(){
expect(toTitleCase('the beautiful dog')).to.equal('The Beautiful Dog');
expect(toTitleCase('for all the deadly ninjas, be it so')).to.equal('For All the Deadly Ninjas Be It So');
expect(toTitleCase('with cats and dogs we are near')).to.equal('With Cats and Dogs We Are Near');
});
it('Replace special characters with space', function(){
expect(toTitleCase('[wolves & lions]: be careful')).to.equal('Wolves & Lions Be Careful');
expect(toTitleCase('wolves & lions, be careful')).to.equal('Wolves & Lions Be Careful');
});
it('Trim whitespace at beginning and end', function(){
expect(toTitleCase(' mario & Luigi superstar saga ')).to.equal('Mario & Luigi Superstar Saga');
});
it('articles, conjunctions and prepositions should not be capitalized in strings of 3+ words', function(){
expect(toTitleCase('The wolf and the lion: a tale of two like animals')).to.equal('The Wolf and the Lion a Tale of Two like Animals');
expect(toTitleCase('the three Musketeers And plus ')).to.equal('The Three Musketeers and Plus');
});
});
Please note that I am removing quite a bit of special characters from the strings provided. You will need to tweak the regex to address the requirements of your project.
If regex used in the above solutions is getting you confused, try this code:
function titleCase(str) {
return str.split(' ').map(function(val){
return val.charAt(0).toUpperCase() + val.substr(1).toLowerCase();
}).join(' ');
}
I made this function which can handle last names (so it's not title case) such as "McDonald" or "MacDonald" or "O'Toole" or "D'Orazio". It doesn't however handle German or Dutch names with "van" or "von" which are often in lower-case... I believe "de" is often lower-case too such as "Robert de Niro". These would still have to be addressed.
function toProperCase(s)
{
return s.toLowerCase().replace( /\b((m)(a?c))?(\w)/g,
function($1, $2, $3, $4, $5) { if($2){return $3.toUpperCase()+$4+$5.toUpperCase();} return $1.toUpperCase(); });
}
Most of these answers seem to ignore the possibility of using the word boundary metacharacter (\b). A shorter version of Greg Dean's answer utilizing it:
function toTitleCase(str)
{
return str.replace(/\b\w/g, function (txt) { return txt.toUpperCase(); });
}
Works for hyphenated names like Jim-Bob too.
First, convert your string
into array by splitting it by spaces:
var words = str.split(' ');
Then use array.map to create a new array containing the capitalized words.
var capitalized = words.map(function(word) {
return word.charAt(0).toUpperCase() + word.substring(1, word.length);
});
Then join the new array with spaces:
capitalized.join(" ");
function titleCase(str) {
str = str.toLowerCase(); //ensure the HeLlo will become Hello at the end
var words = str.split(" ");
var capitalized = words.map(function(word) {
return word.charAt(0).toUpperCase() + word.substring(1, word.length);
});
return capitalized.join(" ");
}
console.log(titleCase("I'm a little tea pot"));
NOTE:
This of course has a drawback. This will only capitalize the first letter of every word. By word, this means that it treats every string separated by spaces as 1 word.
Supposedly you have:
str = "I'm a little/small tea pot";
This will produce
I'm A Little/small Tea Pot
compared to the expected
I'm A Little/Small Tea Pot
In that case, using Regex and .replace will do the trick:
with ES6:
const capitalize = str => str.length
? str[0].toUpperCase() +
str.slice(1).toLowerCase()
: '';
const escape = str => str.replace(/./g, c => `\\${c}`);
const titleCase = (sentence, seps = ' _-/') => {
let wordPattern = new RegExp(`[^${escape(seps)}]+`, 'g');
return sentence.replace(wordPattern, capitalize);
};
console.log( titleCase("I'm a little/small tea pot.") );
or without ES6:
function capitalize(str) {
return str.charAt(0).toUpperCase() + str.substring(1, str.length).toLowerCase();
}
function titleCase(str) {
return str.replace(/[^\ \/\-\_]+/g, capitalize);
}
console.log(titleCase("I'm a little/small tea pot."));
If you can use third party libraries in your code then lodash has a helper function for us.
https://lodash.com/docs/4.17.3#startCase
_.startCase('foo bar');
// => 'Foo Bar'
_.startCase('--foo-bar--');
// => 'Foo Bar'
_.startCase('fooBar');
// => 'Foo Bar'
_.startCase('__FOO_BAR__');
// => 'FOO BAR'
ES 6
str.split(' ')
.map(s => s.slice(0, 1).toUpperCase() + s.slice(1).toLowerCase())
.join(' ')
else
str.split(' ').map(function (s) {
return s.slice(0, 1).toUpperCase() + s.slice(1).toLowerCase();
}).join(' ')
jim-bob -> Jim-Bob
jim/bob -> Jim/Bob
jim_bob -> Jim_Bob
isn't -> Isn't
école -> École
McDonalds -> McDonalds
function toTitleCase(str) {
return str.replace(/\p{L}+('\p{L}+)?/gu, function(txt) {
return txt.charAt(0).toUpperCase() + txt.slice(1)
})
}
var toMatch = "john w. smith";
var result = toMatch.replace(/(\w)(\w*)/g, function (_, i, r) {
return i.toUpperCase() + (r != null ? r : "");
}
)
Seems to work... Tested with the above, "the quick-brown, fox? /jumps/ ^over^ the ¡lazy! dog..." and "C:/program files/some vendor/their 2nd application/a file1.txt".
If you want 2Nd instead of 2nd, you can change to /([a-z])(\w*)/g
.
The first form can be simplified as:
function toTitleCase(toTransform) {
return toTransform.replace(/\b([a-z])/g, function (_, initial) {
return initial.toUpperCase();
});
}
Try this, shortest way:
str.replace(/(^[a-z])|(\s+[a-z])/g, txt => txt.toUpperCase());
Use /\S+/g
to support diacritics:
function toTitleCase(str) {
return str.replace(/\S+/g, str => str.charAt(0).toUpperCase() + str.substr(1).toLowerCase());
}
console.log(toTitleCase("a city named örebro")); // A City Named Örebro
However: "sunshine (yellow)" ⇒ "Sunshine (yellow)"
"john f. kennedy".replace(/\b\S/g, t => t.toUpperCase())
Try this
String.prototype.toProperCase = function(){
return this.toLowerCase().replace(/(^[a-z]| [a-z]|-[a-z])/g,
function($1){
return $1.toUpperCase();
}
);
};
Example
var str = 'john smith';
str.toProperCase();
Here is my function that is taking care of accented characters (important for french !) and that can switch on/off the handling of lowers exceptions. Hope that helps.
String.prototype.titlecase = function(lang, withLowers = false) {
var i, string, lowers, uppers;
string = this.replace(/([^\s:\-'])([^\s:\-']*)/g, function(txt) {
return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
}).replace(/Mc(.)/g, function(match, next) {
return 'Mc' + next.toUpperCase();
});
if (withLowers) {
if (lang == 'EN') {
lowers = ['A', 'An', 'The', 'At', 'By', 'For', 'In', 'Of', 'On', 'To', 'Up', 'And', 'As', 'But', 'Or', 'Nor', 'Not'];
}
else {
lowers = ['Un', 'Une', 'Le', 'La', 'Les', 'Du', 'De', 'Des', 'À', 'Au', 'Aux', 'Par', 'Pour', 'Dans', 'Sur', 'Et', 'Comme', 'Mais', 'Ou', 'Où', 'Ne', 'Ni', 'Pas'];
}
for (i = 0; i < lowers.length; i++) {
string = string.replace(new RegExp('\\s' + lowers[i] + '\\s', 'g'), function(txt) {
return txt.toLowerCase();
});
}
}
uppers = ['Id', 'R&d'];
for (i = 0; i < uppers.length; i++) {
string = string.replace(new RegExp('\\b' + uppers[i] + '\\b', 'g'), uppers[i].toUpperCase());
}
return string;
}
I think the simplest is using css.
function format_str(str) {
str = str.toLowerCase();
return '<span style="text-transform: capitalize">'+ str +'</span>';
}
here's another solution using css (and javascript, if the text you want to transform is in uppercase):
html
<span id='text'>JOHN SMITH</span>
js
var str = document.getElementById('text').innerHtml;
var return_text = str.toLowerCase();
css
#text{text-transform:capitalize;}
Here's a really simple & concise ES6 function to do this:
const titleCase = (str) => {
return str.replace(/\w\S*/g, (t) => { return t.charAt(0).toUpperCase() + t.substr(1).toLowerCase() });
}
export default titleCase;
Works well included in a utilities
folder and used as follows:
import titleCase from './utilities/titleCase.js';
const string = 'my title & string';
console.log(titleCase(string)); //-> 'My Title & String'
I've tested this solution for Turkish and it works with special characters too.
function toTitleCase(str) {
return str.toLocaleLowerCase().replace(
/(^|Ü|ü|Ş|ş|Ç|ç|İ|ı|Ö|ö|\w)\S*/g,
(txt) => txt.charAt(0).toLocaleUpperCase() + txt.substring(1),
)
}
console.log(toTitleCase('İSMAİL HAKKI'))
console.log(toTitleCase('ŞAHMARAN BİNBİR GECE MASALLARI'))
console.log(toTitleCase('TEKNOLOJİ ÜRÜNÜ'))
I've added "toLocaleLowerCase" at the begining since I've all caps data. You can discard it if you don't need it.
Using locale operations is important for non-english languages.
本文标签:
版权声明:本文标题:Convert string to Title Case with JavaScript - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1736663467a1946535.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论