แปลงสตริงเป็นกรณีหัวเรื่องด้วย JavaScript


549

มีวิธีง่ายๆในการแปลงสตริงเป็นกรณีชื่อ? เช่นจะกลายเป็นjohn smith John Smithฉันไม่ได้มองหาบางสิ่งที่ซับซ้อนเช่นวิธีแก้ปัญหาของ John Resigเพียงแค่หวังว่าจะเป็นแบบหนึ่งหรือสองแบบ


มีวิธีการต่าง ๆ เรามีสถิติประสิทธิภาพบ้างไหม?
theAnubhav

โปรดตรวจสอบคำตอบสั้น ๆ นี้stackoverflow.com/a/57689168/10373693 ฉันหวังว่าจะเป็นคำตอบที่คุณกำลังมองหา
Abhishek Kumar

คำตอบ:


740

ลองสิ่งนี้:

    function toTitleCase(str) {
        return str.replace(
            /\w\S*/g,
            function(txt) {
                return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
            }
        );
    }
<form>
Input:
<br /><textarea name="input" onchange="form.output.value=toTitleCase(this.value)"  onkeyup="form.output.value=toTitleCase(this.value)"></textarea>
<br />Output:
<br /><textarea name="output" readonly onclick="select(this)"></textarea>
</form>


14
ใครช่วยอธิบายหน่อยได้ไหมทำไมถึง\w\S*ใช้แทน\w+หรือ\w*ยกตัวอย่าง ผมไม่ทราบว่าทำไมคุณต้องการที่จะรวมถึงอะไร แต่ช่องว่างและดังนั้นจึงเปลี่ยนจิมบ๊อบไปจิมบ๊อบ
martinczerwi

5
@martinCzerwi \w\S*ยังทำให้เกิดJim-bobปัญหาในตอนท้ายของเรา ใช้\w*แก้ไขสิ่งนี้
Bouke

14
/([^\W_]+[^\s-]*) */gแก้Jim-Bobปัญหาคือ:jim-bob --> Jim-Bob
recursion.ninja

15
ถ้าเป็นความปรารถนาของคุณคุณอาจจะต้องทำอย่างไรjim-bob --> Jim-Bob /\b\w+/gตัวอย่าง:str.replace(/\b\w+/g,function(s){return s.charAt(0).toUpperCase() + s.substr(1).toLowerCase();});
vol7ron

3
\w\S*มีการใช้แทน\w+หรือ\w*เพื่อให้คำเช่นDon'tไม่ได้รับการแก้ไขDon'Tแต่เป็นคนอื่น ๆ ได้ชี้ให้เห็น\w\S*สาเหตุของปัญหาด้วยคำที่ใส่ยัติภังค์
doubleDown

198

วิธีที่สวยงามกว่านี้เล็กน้อยปรับฟังก์ชั่นของ Greg Dean:

String.prototype.toProperCase = function () {
    return this.replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();});
};

เรียกว่าชอบ:

"pascal".toProperCase();

3
โปรดทราบว่าคุณมีผู้ใช้ที่มีเส้นประในชื่อของพวกเขาและพวกเขาป้อนJo-Ann Smithรหัสนี้จะแปลงพวกเขาเป็นJo-ann Smith(หมายเหตุตัวพิมพ์เล็กaในAnn)
dbau

18
@daniellmb ทำไมเขาไม่ควรเปลี่ยนเครื่องต้นแบบ String? ฉันคิดว่ามันเป็นทางออกที่ดี คิดว่าคลาสทับทิมเปิดมันถูกต้องสมบูรณ์เพื่อเพิ่มฟังก์ชั่นให้กับคลาสที่มีอยู่และเป็นที่ยอมรับอย่างกว้างขวาง
marco-fiset

97
@ marco-fiset เพราะมันเล่นได้ไม่ดีกับคนอื่น! สิ่งไม่ดีเกิดขึ้นเมื่อคุณมี 2 ไลบรารีที่พยายามแก้ไขวัตถุ JavaScript ดั้งเดิมที่มีการเปลี่ยนแปลงที่เข้ากันไม่ได้ ลองคิดดูว่า jQuery และ Google Maps เป็นไปตามรูปแบบการออกแบบนี้หรือไม่คุณไม่มีทั้งคู่ในหน้าเดียวกัน
daniellmb

5
@daniellmb เป็นจุดที่ยอดเยี่ยม คำนำหน้าชื่อวิธีการควรช่วยหลีกเลี่ยงปัญหานี้เช่นเดียวกับที่จะทำให้วิธีการไม่นับ
mikemaccana

60
ฉันรู้สึกว่าคำสั่ง "ไม่แก้ไขวัตถุ JavaScript ดั้งเดิม" เป็นเหมือน "ไม่เคยใช้ goto" หรือ "eval is evil" มีหลายกรณีที่มันโอเค หากคุณมีการควบคุมโครงการของคุณอย่างสมบูรณ์และแน่นอนไม่ได้วางแผนที่จะปล่อยมันเป็นห้องสมุดฉันไม่เห็นปัญหากับวิธีนี้
FoxMulder900

175

ลองใช้สไตล์ CSS แปลงข้อความกับตัวควบคุมของคุณ

เช่น: (text-transform: capitalize);

ใช้วิธีการ JS เมื่อจำเป็นเท่านั้น


36
-1 css นี้ใช้งานได้ แต่ไม่ได้ผลตามที่คนส่วนใหญ่คาดหวังเพราะถ้าข้อความเริ่มเป็นตัวพิมพ์ใหญ่ทั้งหมดจะไม่มีผลใด ๆ webmasterworld.com/forum83/7506.htm
whitneyland

2
@Akshar: กฎตัวพิมพ์เล็กจะถูกแทนที่ด้วยกฎกรณีและปัญหา เนื่องจาก css ไม่ได้แก้ไขเนื้อหาต้นฉบับผลกระทบก็คือกฎตัวพิมพ์เล็กจะถูกลบออก (ทิ้งเนื้อหาต้นฉบับไว้ในตัวพิมพ์ใหญ่ทั้งหมด) จากนั้นจึงใช้กฎตัวอักษรตัวพิมพ์เล็ก (ไม่ทำอะไรเลย)
dokkaebi

42
JS ใช้นอกเบราว์เซอร์
mikemaccana

4
คำถามคือ: "มีวิธีง่ายๆในการแปลงสตริงเป็นกรณีชื่อ?" . คำตอบนี้ไม่แปลงสตริง นี่คือสไตล์ที่ใช้บนสตริง
kingPuppy

หากคุณต้องการให้ข้อมูลในฐานข้อมูลของคุณสะอาดเพื่อให้สามารถใช้งานได้อย่างสมบูรณ์เมื่อส่งผ่านไปยังบริการบุคคลที่สามหรือส่งออกเป็น CSV แล้ว CSS ไม่ใช่ตัวเลือกจริงๆ CSS มีไว้สำหรับเครื่องสำอางและในขณะที่มันโตขึ้นมากในช่วงหลายปีที่ผ่านมาและคุณสามารถใช้มันเพื่อแก้ปัญหาแบบนี้ได้วิธีแก้ปัญหายังคงเป็นเครื่องสำอางและไม่สามารถแก้ปัญหาพื้นฐานได้
Adam Reis

118

นี่คือเวอร์ชั่นของฉัน IMO มันเข้าใจง่ายและสง่างามเช่นกัน

var str = "foo bar baz"

console.log(

str.split(' ')
   .map(w => w[0].toUpperCase() + w.substr(1).toLowerCase())
   .join(' ')

)
// returns "Foo Bar Baz"


3
อีกวิธีหนึ่งคุณสามารถพิมพ์อักษรตัวเล็กลงในแผนที่ย่อยได้:str.split(' ').map(i => i[0].toUpperCase() + i.substring(1).toLowerCase()).join(' ')
Dave Land

5
.toLowerCase()ผมไม่เห็นด้วยกับการเรียก ชื่อเช่น "McDonald" หรือตัวย่อเช่น "ASAP" ควรใช้อักขระตัวพิมพ์ใหญ่ หากมีใครบางคนส่งผ่านสตริงเช่น "heLLO" แอปพลิเคชันไม่ควรถือว่าตัวอักษรตัวพิมพ์ใหญ่ไม่ถูกต้อง
โทมัส Higginbotham

1
@ThomasHigginbotham เป็นไงบ้าง? String.prototype.toTitleCase = function (blnForceLower) { var strReturn; (blnForceLower ? strReturn = this.toLowerCase() : strReturn = this); return strReturn .split(' ') .map(i => i[0].toUpperCase() + i.substr(1)) .join(' '); }
Sean Kendle

ใช่จัดให้มีตัวเลือกในการบังคับตัวพิมพ์เล็ก
โทมัส Higginbotham

1
สิ่งนี้จะแตกถ้าstrเป็นอักขระตัวเดียว
Madbreaks

103

นี่คือฟังก์ชันของฉันที่แปลงเป็นชื่อตัวพิมพ์ แต่ยังคงคำย่อที่กำหนดไว้เป็นตัวพิมพ์ใหญ่และคำย่อยเป็นตัวพิมพ์เล็ก

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;
}

ตัวอย่างเช่น:

"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:"

1
ฉันชอบของคุณฉันยังพบปัญหาเมื่อต้องรับมือกับตัวเลขโรมัน ... เพิ่งแก้ไขมันด้วย I, II, III, IV และอื่น ๆ
Marcelo

2
แก้ไขแล้ว. regex ในบรรทัดที่สามถูกเปลี่ยนจาก/\w\S*/gเป็น/([^\W_]+[^\s-]*) */gต่อความคิดเห็นของ @ awashburn ด้านบนเพื่อแก้ไขปัญหานี้
เจฟฟรีย์บูธ

2
มีข้อดีที่จะได้รับจากการใช้รูปแบบ regex ของคุณมากกว่า/\b\w+/gซึ่งฉันคิดว่าเข้าใจได้เร็วขึ้นหรือไม่
ไมเคิล - ที่ไหน Shirky นวล

2
ไม่ใช่ที่ฉันเห็นฉันแค่รับข้อเสนอแนะจากผู้วิจารณ์คนอื่นเพื่อแก้ปัญหาคำที่ใส่ยัติภังค์ แต่ regex ของคุณดูเหมือนจะทำเช่นกันและความเรียบง่ายดีกว่าเสมอ สำหรับผู้เยี่ยมชมและผู้เยี่ยมชมในอนาคตที่โพสต์นี้ฉันเพิ่งเปลี่ยน regex ในบรรทัดที่สามจาก/([^\W_]+[^\s-]*) */gเป็น/\b\w+/gต่อความคิดเห็นของ @ Michael; โปรดแสดงความคิดเห็นหากคุณพบกรณีที่จำเป็นต้องใช้ regex ที่ซับซ้อนมากขึ้น
Geoffrey Booth

1
ฉันเปลี่ยน regex บรรทัดที่ 3 เป็น/\b[\w-\']+/gคำที่อนุญาตให้ใช้เครื่องหมายยัติภังค์และเครื่องหมายอัญประกาศเดี่ยวในคำ
Shamasis Bhattacharya

47

ฉันชอบสิ่งต่อไปนี้มากกว่าคำตอบอื่น ๆ มันจับคู่เพียงตัวอักษรตัวแรกของแต่ละคำและใช้ตัวพิมพ์ใหญ่ รหัสเรียบง่ายอ่านง่ายขึ้นและน้อยกว่าไบต์ มันรักษาตัวอักษรที่มีอยู่เพื่อป้องกันการบิดเบือนคำย่อ อย่างไรก็ตามคุณสามารถโทรหาสายtoLowerCase()ของคุณก่อนเสมอ

function title(str) {
  return str.replace(/(^|\s)\S/g, function(t) { return t.toUpperCase() });
}

คุณสามารถเพิ่มสิ่งนี้ลงในต้นแบบเครื่องสายของคุณซึ่งจะช่วยให้คุณ'my string'.toTitle()ดังต่อไปนี้:

String.prototype.toTitle = function() {
  return this.replace(/(^|\s)\S/g, function(t) { return t.toUpperCase() });
}

ตัวอย่าง:


3
ก็จะยิ่งดีกว่าเป็นแลมบ์ดาconst titleCase = (str) => str.replace(/\b\S/g, t => t.toUpperCase());
0xcaff

ฉันไม่ต้องการทำลาย IE แต่ใช่ถ้าแอปพลิเคชันไม่ใช่เบราว์เซอร์ดั้งเดิมที่ละเอียดอ่อนมันอาจสั้นลง
Tom Kay

นี่เป็นเพียงวิธีการแก้ปัญหาบางส่วน - op ถามถึงวิธีการแปลงสตริงเป็นกรณีตัวพิมพ์ใหญ่ NoT qUiITeคำตอบนี้ไม่ประสบความสำเร็จว่าสำหรับปัจจัยการผลิตเช่น
Madbreaks

@Madbreaks คำถามไม่ได้ระบุว่าควรแปลงแปลงตัวพิมพ์เล็กและใหญ่ อย่างไรก็ตามฉันได้อัปเดตคำตอบที่กล่าวถึงtoLowerCaseแล้ว เพิ่งทราบว่ามันจะทำลายคำย่อ an HTML document: An HTML DocumentvsAn Html Document
Tom Kay

4
@Madbreaks ในขณะที่ตัวอย่างแรกของคุณมีการวางแผนคุณทำดีในการระบุว่าผลลัพธ์จะไม่เปลี่ยนแปลงถ้าอินพุทเป็นตัวพิมพ์ใหญ่ ที่ถูกกล่าวว่าฉันรู้สึกคำตอบตามที่เป็นอยู่toLowerCase ) มีความยืดหยุ่น / มีประโยชน์มากกว่าหนึ่งซึ่งถือว่าความตั้งใจของนักพัฒนา วิธีนี้ยังสะท้อนถึงการทำงานของวิธีการที่มีอยู่ในตัวของภาษาอื่นเช่น PHP ( ucwords) และ Golang ( strings.Title) .NET ( TextInfo.ToTitleCase) ทำงานได้อย่างน่าสนใจสำหรับกรณีที่มีหลายกรณี แต่จะปล่อยให้สตริงตัวพิมพ์ใหญ่ไม่เปลี่ยนแปลง
Tom Kay

20

โดยไม่ใช้ regex เพียงเพื่อการอ้างอิง:

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()
)


ขอบคุณสำหรับโซลูชันฟรีของ regex!
lucifer63

20

var result =
  'this is very interesting'.replace(/\b[a-z]/g, (x) => x.toUpperCase())

console.log(result) // This Is Very Interesting


เพียงแค่คำถามโครงสร้าง () นั้นใช้สำหรับระบุการจับคู่ตามลำดับตัวเลือกใด ๆ : นั่นคือ (a | b) ตรงกับ a หรือ b การก่อสร้าง (.) ทำอะไร
Michael Blackburn

สำหรับทุกคนที่มีคำถามเดียวกันจะกำหนด "blob" สำรองซึ่งใช้ในส่วนทดแทน Blobs นั้นมีหมายเลขตามลำดับตัวแรก () จะใส่ใน $ 1 ส่วนที่สองเป็น $ 2 ฉันพบว่าไซต์นี้มีประโยชน์: javascript.info/tutorial/regular-expressions-methods
Michael Blackburn

ฉันไม่สามารถทำงานดังกล่าวได้ แต่ฉันยังห่างไกลจากตัวช่วยสร้าง regex ฉันใช้ 'string'.replace(/^(.)(.*)/,function(s,p1,p2){return p1.toUpperCase()+p2;}) อีกครั้งนี่ใช้งานได้กับการใช้อักษรตัวแรกของสตริงเท่านั้น แต่ในกรณีที่คุณต้องการงานก่อสร้างของฉัน
Michael Blackburn

1
ด้วยเหตุผลบางอย่างที่ FF35 ดูเหมือนจะทำให้หายใจไม่ออก'$1'.toUpperCase()ดูเหมือนว่าตัวพิมพ์ใหญ่จะยังไม่เสร็จตามเวลาที่กำหนดไว้ ทำงานโดยใช้ฟังก์ชั่น'string'.replace(/^(.){1}/,function(match) { return match.toUpperCase(); })
MrYellow

สวัสดีทุกคำตอบได้รับการแก้ไข! ฉันค่อนข้างแน่ใจว่ามันทำงานตามเวลาที่ฉันโพสต์ครั้งแรก อย่างไรก็ตามขอขอบคุณสำหรับการป้อนข้อมูล!
simo

17

คุณสามารถtoLowerCaseสตริงได้ทันทีจากนั้นก็แค่toUpperCaseตัวอักษรตัวแรกของแต่ละคำ กลายเป็น 1 ซับง่าย ๆ :

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

console.log(titleCase('iron man'));
console.log(titleCase('iNcrEdible hulK'));


ฉันชอบวิธีนี้ ดีและเรียบง่าย ดูเหมือนว่า CoffeeScript จะลื่นไหลไปกับคำตอบของคุณ ( s => s.toUpperCase()) ตัวแปรของฉันคือการทำในสิ่งที่คุณได้กระทำ แต่การขยายวัตถุสตริง (เป็นที่ถกเถียงกันในฐานะที่):Object.defineProperty(String.prototype, '_toProperCase', {value:function() {return this.toLowerCase().replace(/\b(\w)/g, function(t) {return t.toUpperCase()})}})
Waz

1
@ Waz ขอบคุณสำหรับความคิด! แค่ต้องการอธิบายให้ชัดเจน=>ว่าเป็นฟังก์ชั่นลูกศรแบบดั้งเดิม (ES6) ลิงก์จะข้ามไปที่ Mozillla Docs ของพวกเขาซึ่งมีตารางการสนับสนุน
KevBot

16

ในกรณีที่คุณกังวลเกี่ยวกับคำที่เติมคุณสามารถบอกฟังก์ชั่นที่จะไม่ใช้ประโยชน์

/**
 * @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();
    });
};

หวังว่านี่จะช่วยคุณได้

แก้ไข

หากคุณต้องการจัดการคำกาวชั้นนำคุณสามารถติดตามตัวแปร w ​​/ นี้อีกหนึ่งตัวแปร:

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;
    });
};

2
คุณสามารถระเบิดสตริงลงในอาร์เรย์ ดังนั้นเราอาจมีคำบุพบทภาษาโปรตุเกสภาษาสเปนภาษาอิตาลีและภาษาฝรั่งเศส:glue ='de|da|del|dos|do|das|des|la|della|delli'.split('|');
จูเนียร์เมเช่

สิ่งนี้จะไม่รับประกันการใช้อักษรตัวพิมพ์ใหญ่ของคำแรก คือจะกลายเป็นand another thing and Another Thingเพียงแค่ต้องใช้วิธีที่สง่างามเพื่อใช้ประโยชน์จากคำแรกเสมอ
แบรดโคช์

@BradKoch - เติมช่องว่างเพื่อให้คุณใช้ 'และ', 'de' ฯลฯ เป็นคำค้นหาแล้ว 'และอีกคนหนึ่ง' จะแทนที่ 'และอื่น ๆ อีก'
Yimin Rong

ดียกเว้นมันจะทำให้ข้อความเป็นตัวพิมพ์ใหญ่หลังจาก 'and - like H'Dy หรือ Number-One
luky

แทนที่จะใช้ผู้ประกอบการที่ประกอบไปด้วยรถคุณก็สามารถใช้ทางเลือกแทนได้: glue = glue || ['ของ', 'สำหรับ', 'และ', 'a'];
tm2josep

14

หาก regex ที่ใช้ในการแก้ปัญหาข้างต้นทำให้คุณสับสนลองรหัสนี้:

function titleCase(str) {
  return str.split(' ').map(function(val){ 
    return val.charAt(0).toUpperCase() + val.substr(1).toLowerCase();
  }).join(' ');
}

รักมัน! ไม่มีการแปลงเป็นอาร์เรย์
neelmeg

1
uhhh ... split ไม่แปลงเป็นอาร์เรย์คุณก็ไม่เห็นว่ามันเป็นอย่างเห็นได้ชัดเพราะmapหมายความว่าคุณจะได้ไม่ต้องใช้[]สัญกรณ์
MalcolmOcean

2
นี่เป็นคำตอบเดียวกับa8mจาก 2 ปีก่อน
ไมเคิล - Clay Shirky อยู่ที่ไหน

1
ตัวแบ่งสำหรับอินพุตแบบ Char เดียว
Madbreaks

1
@AlexChaffee ตรวจสอบประวัติการแก้ไข a8m ไม่ได้ใช้ฟังก์ชั่นลูกศรในคำตอบเดิม
ขอบคุณ

9

ฉันสร้างฟังก์ชั่นนี้ซึ่งสามารถรองรับนามสกุล (ดังนั้นจึงไม่ใช่กรณีที่มีชื่อ) เช่น "McDonald" หรือ "MacDonald" หรือ "O'Toole" หรือ "D'Orazio" อย่างไรก็ตามมันไม่ได้จัดการชื่อเยอรมันหรือดัตช์ด้วย "van" หรือ "von" ซึ่งมักจะเป็นตัวพิมพ์เล็ก ... ฉันเชื่อว่า "de" มักจะเป็นตัวพิมพ์เล็กเช่น "Robert de Niro" สิ่งเหล่านี้จะต้องได้รับการแก้ไข

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(); });
}

1
+1 สำหรับการรับรู้ชื่อ ไม่จัดการ "macy" อย่างถูกต้องเช่นกัน
ไบรอันรี่

นี่เป็นฟังก์ชั่นเดียวที่จัดการการแปลงตัวพิมพ์ใหญ่และตัวพิมพ์เล็กอย่างถูกต้องเป็นกรณีที่ถูกต้องและสังเกตว่าอักษรตัวเล็กเช่น "US Virgin Islands"
Rodrigo Polo

คุณสามารถmacyแก้ไขปัญหานี้ได้โดยใส่เครื่องหมายลบในนั้นจึง\b((m)(a?c))?(\w)กลายเป็น\b((m)(a?c))?(\w)(?!\s)
Ste

8
var toMatch = "john w. smith";
var result = toMatch.replace(/(\w)(\w*)/g, function (_, i, r) {
      return i.toUpperCase() + (r != null ? r : "");
    }
)

ดูเหมือนว่าจะทำงาน ... ผ่านการทดสอบข้างต้น "the quick-brown, fox? / jumps / ^ over ^ the ¡ lazy! dog ... " และ "C: / ไฟล์โปรแกรม / ผู้ขายบางราย / แอปพลิเคชันที่สอง / a file1.txt"

หากคุณต้องการ 2Nd แทน 2nd คุณสามารถเปลี่ยนเป็น /([a-z])(\w*)/gคุณสามารถเปลี่ยนไป

แบบฟอร์มแรกสามารถทำให้ง่ายขึ้นเป็น:

function toTitleCase(toTransform) {
  return toTransform.replace(/\b([a-z])/g, function (_, initial) {
      return initial.toUpperCase();
  });
}

7

ลองสิ่งนี้

String.prototype.toProperCase = function(){
    return this.toLowerCase().replace(/(^[a-z]| [a-z]|-[a-z])/g, 
        function($1){
            return $1.toUpperCase();
        }
    );
};

ตัวอย่าง

var str = 'john smith';
str.toProperCase();

7

หากคุณสามารถใช้ห้องสมุดบุคคลที่สามในรหัสของคุณแล้ว lodash มีฟังก์ชั่นตัวช่วยสำหรับเรา

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'



7

ES 6

str.split(' ')
   .map(s => s.slice(0, 1).toUpperCase() + s.slice(1).toLowerCase())
   .join(' ')

อื่น

str.split(' ').map(function (s) {
    return s.slice(0, 1).toUpperCase() + s.slice(1).toLowerCase();
}).join(' ')

เพียงหัวขึ้นอาจจะs.slice(0, 1).toUpperCase()ถ้าคุณยังต้องการตัวอักษรตัวแรกที่
WindsofTime

@jssridhar คุณควรแก้ไขรหัสใน ES6
caiosm1005

1
แตกถ้าstrเป็นตัวละครตัวเดียว
Madbreaks

@jssridhar .charAt(0).toUpperCase()อาจจะดีกว่าที่จะให้เรา
roydukkey

2
ซ้ำกับคำตอบของ a8m
ขอบคุณ

6

คำตอบเหล่านี้ส่วนใหญ่ดูเหมือนจะเพิกเฉยต่อความเป็นไปได้ที่จะใช้คำว่า metacharacter (\ b) คำตอบสั้น ๆ ของ Greg Dean ใช้:

function toTitleCase(str)
{
    return str.replace(/\b\w/g, function (txt) { return txt.toUpperCase(); });
}

ใช้งานได้กับชื่อยัติภังค์เช่น Jim-Bob ด้วย


2
เป็นวิธีการแก้ปัญหาบางส่วนที่สวยงาม แต่ไม่ได้ทำงานกับสตริงตัวพิมพ์ใหญ่หรือตัวพิมพ์ใหญ่ ฉันได้รับ "Sofía Vergara" => "SofíA Vergara" หรือ "Sofía VergARA" => "SofíA VergARA" กรณีที่สองสามารถแก้ไขได้โดยใช้ฟังก์ชั่น. toLowerCase () ก่อน. แทนที่ (... ) กรณีแรกต้องค้นหานิพจน์ปกติที่ถูกต้อง
Asereware

2
อืมดูเหมือนว่ามีข้อบกพร่องในการใช้งาน regex ฉันคิดว่าตัวอักษรที่เน้นเสียงควรเป็นตัวอักษรคำ (คุณพูดถูก แต่มันไม่ได้ผลสำหรับกรณีเหล่านั้น)
lewax00

\wมีเฉพาะอักขระ[A-Za-z0-9_]เท่านั้นไม่ใช่ตัวอักษรทั้งหมด \p{L}สำหรับสิ่งที่คุณจะต้องใช้หมวดหมู่ Unicode คุณจะต้อง/uปรับปรุง (ดูที่นี่ ) และวิธีการแก้ปัญหาที่แตกต่างกันสำหรับ\bซึ่งทำงานระหว่าง\Wและ\w(ดูที่นี่ )
cmbuckley

6

ฉันคิดว่าวิธีที่ง่ายที่สุดคือการใช้ css

function format_str(str) {
    str = str.toLowerCase();
    return '<span style="text-transform: capitalize">'+ str +'</span>';
}

ฉันอัปเดตรหัสและทดสอบแล้ว มันควรจะทำงานตอนนี้
wondim

คุณสามารถใช้ CSS ในสภาพแวดล้อมเพียงส่วนเดียวที่ใช้ JS ดังนั้นโซลูชันนี้จึงไม่สามารถใช้งานได้ ควรหลีกเลี่ยงรูปแบบอินไลน์ด้วยค่าใช้จ่ายทั้งหมด
Madbreaks

5

ใช้/\S+/gเพื่อสนับสนุนกำกับออกเสียง:

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

อย่างไรก็ตาม " s unshine ( Y ellow)" ⇒ " S unshine ( Y ellow)"


5

ฉันต้องการที่จะเพิ่มคำตอบของตัวเองเพราะฉันต้องการtoTitleCaseฟังก์ชั่นที่มีประสิทธิภาพซึ่งคำนึงถึงกฎไวยากรณ์ที่ระบุไว้ที่นี่ (บทความแนะนำจาก Google) มีกฎต่าง ๆ ที่ขึ้นอยู่กับความยาวของสายป้อน ด้านล่างเป็นการทดสอบฟังก์ชั่น + หน่วย

ฟังก์ชั่นนี้ยังรวมถึงช่องว่างและลบอักขระพิเศษ (แก้ไข regex สำหรับความต้องการของคุณ)

ฟังก์ชัน toTitleCase

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(' ');
}

ทดสอบหน่วยเพื่อให้แน่ใจว่าถูกต้อง

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');
  });
});

โปรดทราบว่าฉันกำลังลบตัวอักขระพิเศษออกเล็กน้อยจากสตริงที่ให้ไว้ คุณจะต้องปรับแต่ง regex เพื่อตอบสนองความต้องการของโครงการของคุณ


ฉันชอบโซลูชันนี้เพราะดูแลตัวพิมพ์ใหญ่ ๆ มันไม่ใช่ "Gone With The Wind" มันเป็น "Gone with the Wind"
russellmania

5
"john f. kennedy".replace(/\b\S/g, t => t.toUpperCase())

1
การทำงานสำหรับตัวอย่างและแต่ไม่สิ่งแปลกกับo'henry horse's mouth
ไมเคิล - Clay Shirky

"john f. kennEdy".toLowerCase().replace(/\b\S/g, t => t.toUpperCase())ดีกว่า🤔
w3debugger

ไม่ต้องการแก้ไขคำตอบของ @ Proximo: \bและ\Sเป็นคลาสอักขระพิเศษที่แสดงถึง "ขอบเขตของคำ" และ "อักขระเดียว, ไม่ใช่ช่องว่าง ดังนั้น regex จึงจับคู่อักขระทุกตัวที่อยู่ถัดจากขอบเขตของคำและใช้ประโยชน์จากตัวอักษรนั้นโดยใช้ฟังก์ชันลูกศรที่กำหนด
เจนส์

4

การใช้โซลูชัน "lewax00" ฉันสร้างโซลูชันง่าย ๆ นี้ที่บังคับให้ "w" เริ่มต้นด้วยช่องว่างหรือ "w" ที่เริ่มต้นคำ แต่ไม่สามารถลบช่องว่างกลางพิเศษ

"SOFÍA vergara".toLowerCase().replace(/\b(\s\w|^\w)/g, function (txt) { return txt.toUpperCase(); });

ผลลัพธ์คือ "Sofía Vergara"


4

นี่คือฟังก์ชั่นของฉันที่ดูแลตัวละครที่เน้นเสียง (สำคัญสำหรับภาษาฝรั่งเศส!) และสามารถเปิด / ปิดการจัดการข้อยกเว้นที่ลดลงได้ หวังว่าจะช่วย

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;
}

4

เราได้มีการพูดคุยกันที่นี่ที่สำนักงานและเราคิดว่าการพยายามแก้ไขชื่อผู้ใช้ให้เป็นปัจจุบันในแบบที่คุณต้องการโดยอัตโนมัตินั้นเต็มไปด้วยปัญหาที่อาจเกิดขึ้น

เรามีหลายกรณีที่การใช้ตัวพิมพ์ใหญ่แบบอัตโนมัติแตกต่างกันและนี่เป็นเพียงชื่อภาษาอังกฤษเพียงอย่างเดียวแต่ละภาษามีความซับซ้อนของตัวเอง

ปัญหาเกี่ยวกับการใช้อักษรตัวใหญ่ของชื่อแต่ละตัว:

•คำย่อเช่น IBM ไม่ได้รับอนุญาตให้ป้อนเข้าจะกลายเป็น IBM

•ชื่อ McDonald จะกลายเป็น Mcdonald ซึ่งไม่ถูกต้องสิ่งเดียวกันคือ MacDonald เช่นกัน

•ชื่อที่ลำกล้องสองครั้งเช่น Marie-Tonks จะกลายเป็น Marie-tonks

•ชื่ออย่าง O'Connor จะกลายเป็น O'connor

สำหรับสิ่งเหล่านี้ส่วนใหญ่คุณสามารถเขียนกฎที่กำหนดเองเพื่อจัดการกับมันอย่างไรก็ตามสิ่งนี้ยังคงมีปัญหาเกี่ยวกับตัวย่อเหมือนเมื่อก่อนและคุณจะได้รับปัญหาใหม่:

•การเพิ่มกฎเพื่อแก้ไขชื่อด้วย Mac เช่น MacDonald ชื่อตัวแบ่งเช่น Macy จะเปลี่ยนเป็น MacY

ทางออกเดียวที่เราเกิดขึ้นกับสิ่งที่ไม่ถูกต้องก็คือการใช้ประโยชน์จากตัวอักษรทุกตัวซึ่งเป็นวิธีบังคับเดรัจฉานที่ DBS ใช้

ดังนั้นหากคุณต้องการทำให้กระบวนการเป็นไปโดยอัตโนมัติมันเป็นเรื่องที่เป็นไปไม่ได้ที่จะทำโดยไม่มีพจนานุกรมของชื่อและคำทุกคำและมันควรจะเป็นตัวพิมพ์ใหญ่อย่างไรถ้าคุณไม่มีกฎที่ครอบคลุมทุกอย่างไม่ใช้มัน จะรบกวนผู้ใช้ของคุณและแจ้งให้ผู้ที่ต้องการป้อนชื่ออย่างถูกต้องเพื่อไปที่อื่น


4

นี่คือวิธีแก้ไขปัญหาอื่นโดยใช้ css (และ javascript หากข้อความที่คุณต้องการแปลงเป็นตัวพิมพ์ใหญ่):

HTML

<span id='text'>JOHN SMITH</span>

js

var str = document.getElementById('text').innerHtml;
var return_text = str.toLowerCase();

CSS

#text{text-transform:capitalize;}

3

สำหรับพวกเราที่กลัวการแสดงออกปกติ (หัวเราะ):

function titleCase(str)
{
    var words = str.split(" ");
    for ( var i = 0; i < words.length; i++ )
    {
        var j = words[i].charAt(0).toUpperCase();
        words[i] = j + words[i].substr(1);
    }
    return words.join(" ");
}


3

โซลูชันบรรทัดเดียวของฉัน:

String.prototype.capitalizeWords = function() {
    return this.split(" ").map(function(ele){ return ele[0].toUpperCase() + ele.slice(1).toLowerCase();}).join(" ");
};

จากนั้นคุณสามารถเรียกใช้เมธอดcapitalizeWords()บนสตริงใดก็ได้ ตัวอย่างเช่น:

var myS = "this actually works!";
myS.capitalizeWords();

>>> This Actually Works

โซลูชันอื่นของฉัน:

function capitalizeFirstLetter(word) {
    return word[0].toUpperCase() + word.slice(1).toLowerCase();
}
String.prototype.capitalizeAllWords = function() {
    var arr = this.split(" ");
    for(var i = 0; i < arr.length; i++) {
        arr[i] = capitalizeFirstLetter(arr[i]);
    }
    return arr.join(" ");
};

จากนั้นคุณสามารถเรียกใช้เมธอดcapitalizeWords()บนสตริงใดก็ได้ ตัวอย่างเช่น:

var myStr = "this one works too!";
myStr.capitalizeWords();

>>> This One Works Too

โซลูชันทางเลือกที่อิงตามคำตอบของ Greg Dean:

function capitalizeFirstLetter(word) {
    return word[0].toUpperCase() + word.slice(1).toLowerCase();
}
String.prototype.capitalizeWords = function() {
    return this.replace(/\w\S*/g, capitalizeFirstLetter);
};

จากนั้นคุณสามารถเรียกใช้เมธอดcapitalizeWords()บนสตริงใดก็ได้ ตัวอย่างเช่น:

var myString = "yes and no";
myString.capitalizeWords()

>>> Yes And No

3

แปลกใจที่ไม่มีใครพูดถึงการใช้พารามิเตอร์ที่เหลือ นี่คือซับง่ายๆหนึ่งที่ใช้พารามิเตอร์ ES6 Rest

let str="john smith"
str=str.split(" ").map(([firstChar,...rest])=>firstChar.toUpperCase()+rest.join("").toLowerCase()).join(" ")
console.log(str)


2

สิ่งนี้ขึ้นอยู่กับโซลูชันของฉันสำหรับ"ชื่อคดี" ของกองไฟซึ่งเป็น FreeCodeCampซึ่งคุณต้องแปลงสตริงที่กำหนดให้เป็นตัวพิมพ์เล็กทั้งหมดก่อนแล้วจึงแปลงอักขระทุกตัวที่ดำเนินการเว้นวรรคเป็นตัวพิมพ์ใหญ่

โดยไม่ใช้ regex:

function titleCase(str) {
 return str.toLowerCase().split(' ').map(function(val) { return val.replace(val[0], val[0].toUpperCase()); }).join(' ');
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.