ฉันจะใช้อักษรตัวแรกของชื่อและนามสกุลใน C # ได้อย่างไร


141

มีวิธีที่ง่ายที่จะใช้อักษรตัวแรกของสตริงและลดส่วนที่เหลือของมัน? มีวิธีการในตัวหรือฉันต้องทำเอง


3
ฉันไม่รู้อะไรเกี่ยวกับแอปพลิเคชันของคุณโดยเฉพาะ แต่ฉันคิดว่าคำเตือนทั่วไปมีกำหนด: โปรแกรมเมอร์ไม่ควรใช้วิธีนี้โดยเจตนากับชื่อจริง ฉันคิดว่าจอห์นแมคโดนัลด์เก่าจะไม่พอใจวิธีนี้ที่ทำให้ชื่อของเขาไม่พูดถึง ee cummings, ตะขอแขวน, danah boyd, 松本行弘, คนที่มี "von" ในนามสกุล, คนที่มีนามสกุล "O'Doyle" ฯลฯ ฯลฯ ฯลฯ ชื่อส่วนใหญ่ไม่อยู่ในรูปแบบ "First Last" ที่มีการใช้อักษรตัวใหญ่ (และเป็นตัวอักษรที่สามารถพิมพ์ได้); ฉันขอแนะนำให้อ่านkalzumeus.com/2010/06/17/…
นิค

@Nick ถูกต้องอย่างแน่นอน คุณไม่สามารถสันนิษฐานได้ว่าตัวพิมพ์เล็กและตัวพิมพ์ใหญ่ผิด - ชื่อชาวไอริชทำสิ่งต่าง ๆ เช่น "Ó hAirt" สมมติว่าสำหรับการประชุมใด ๆ ที่คุณสามารถนึกถึงส่วนบนสุดของหัวของคุณจะมีวัฒนธรรม / ภาษาที่จะทำให้คุณประหลาดใจ
James Moore

คำตอบ:


259

TextInfo.ToTitleCase()ใช้อักษรตัวแรกในแต่ละโทเค็นของสตริง
หากมีความจำเป็นต้องรักษาตัวย่อ Uppercasing ToLower()แล้วคุณควรจะรวมถึง

string s = "JOHN DOE";
s = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(s.ToLower());
// Produces "John Doe"

หาก CurrentCulture ไม่พร้อมใช้งานให้ใช้:

string s = "JOHN DOE";
s = new System.Globalization.CultureInfo("en-US", false).TextInfo.ToTitleCase(s.ToLower());

ดูลิงก์ MSDNสำหรับคำอธิบายโดยละเอียด


24
สิ่งหนึ่งที่ควรทราบที่นี่คือมันไม่ทำงานหากสตริงเป็นตัวพิมพ์ใหญ่ทั้งหมด มันคิดว่าตัวพิมพ์ใหญ่ทั้งหมดเป็นตัวย่อ
Mike Roosa

9
สิ่งที่ฉันเห็นด้วยหลายสิ่งเหล่านี้คือคุณไม่สามารถไว้ใจพวกเขาได้ มันจะไม่ทำงานถ้าชื่อนั้นเป็นของ McCain หรือถ้าคุณเริ่มตีชื่อต่างชาติมากกว่านี้
Mike Wills

25
@roosa - แก้ไขง่าย ๆ สำหรับ ToTitleCase (val.ToLower ())
Simon_Weaver

+1 ฉันรู้ว่าต้องอยู่ใน FCL แล้วและ google พาฉันมาที่นี่ = D
gideon

13
ต่างจากคำตอบของนาธานด้านล่างฉันได้รับข้อผิดพลาด: "ต้องมีการอ้างอิงวัตถุสำหรับเขตข้อมูลวิธีการหรือคุณสมบัติคงที่ ....... " โชคไม่ดี
Dan W

117
CultureInfo.CurrentCulture.TextInfo.ToTitleCase("hello world");

อ๊ะ! คำตอบที่ดี. ฉันมักจะลืมเรื่องโลกาภิวัตน์
Michael Haren

สุดยอดทางออก! ใน VB.Net:sItem = Globalization.CultureInfo.CurrentCulture.TextInfo.ToTitleCase(sItem.ToLower) 'first char upper case
Nasenbaer

คุณต้องตรวจสอบวัฒนธรรมของแต่ละชื่อไม่ใช่วัฒนธรรมปัจจุบัน สิ่งนี้ใช้ไม่ได้กับชื่อ
James Moore

1
เนื่องจากสิ่งนี้ขึ้นอยู่กับCurrentCultureว่าเราจะมั่นใจได้อย่างไรว่าไม่มีวัฒนธรรมใดที่จัดการสิ่งนี้แตกต่างกันอย่างไร
Rudey

30
String test = "HELLO HOW ARE YOU";
string s = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(test);

รหัสข้างต้นจะไม่ทำงาน .....

ดังนั้นใส่รหัสด้านล่างโดยแปลงเป็นต่ำกว่าจากนั้นใช้ฟังก์ชั่น

String test = "HELLO HOW ARE YOU";
string s = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(test.ToLower());

15

มีบางกรณีที่CultureInfo.CurrentCulture.TextInfo.ToTitleCaseไม่สามารถจัดการตัวอย่างเช่น: 'วรรค

string input = CultureInfo.CurrentCulture.TextInfo.ToTitleCase("o'reilly, m'grego, d'angelo");
// input = O'reilly, M'grego, D'angelo

regexยังสามารถใช้\b[a-zA-Z]ในการระบุตัวอักษรเริ่มต้นของคำว่าหลังจากขอบเขตคำ\bแล้วเราต้องการเพียงเพื่อแทนที่การแข่งขันโดยขอบคุณกรณีที่เท่าเทียมกันของบนไปที่Regex.Replace(string input,string pattern,MatchEvaluator evaluator)วิธีการ:

string input = "o'reilly, m'grego, d'angelo";
input = Regex.Replace(input.ToLower(), @"\b[a-zA-Z]", m => m.Value.ToUpper());
// input = O'Reilly, M'Grego, D'Angelo

regexสามารถปรับถ้าจำเป็นตัวอย่างเช่นถ้าเราต้องการที่จะจัดการMacDonaldและMcFryกรณี regex จะกลายเป็น:(?<=\b(?:mc|mac)?)[a-zA-Z]

string input = "o'reilly, m'grego, d'angelo, macdonald's, mcfry";
input = Regex.Replace(input.ToLower(), @"(?<=\b(?:mc|mac)?)[a-zA-Z]", m => m.Value.ToUpper());
// input = O'Reilly, M'Grego, D'Angelo, MacDonald'S, McFry

ถ้าเราต้องการที่จะจัดการกับคำนำหน้ามากขึ้นเราจะต้องปรับเปลี่ยนกลุ่ม(?:mc|mac)เช่นการเพิ่มคำนำหน้าฝรั่งเศส:du, de(?:mc|mac|du|de)

สุดท้ายเราสามารถรู้ว่านี่regexยังจะตรงกับกรณีMacDonald'Sสำหรับที่ผ่านมา'sดังนั้นเราต้องจัดการกับมันในregex(?<!'s\b)กับเบื้องหลังมองเชิงลบ ในตอนท้ายเรามี:

string input = "o'reilly, m'grego, d'angelo, macdonald's, mcfry";
input = Regex.Replace(input.ToLower(), @"(?<=\b(?:mc|mac)?)[a-zA-Z](?<!'s\b)", m => m.Value.ToUpper());
// input = O'Reilly, M'Grego, D'Angelo, MacDonald's, McFry

@polkduran ฉันพยายามหาวิธีจัดการกับตัวเลขโรมันในตอนท้ายของชื่อ; ฉันต้องการทำให้มันเป็นตัวพิมพ์ใหญ่ทั้งหมด: John Smith III การมองด้านลบเชิงลบจะรบกวนสิ่งนี้หรือไม่?
Matt

ตามปกติแล้วในที่สุดฉันก็สามารถตอบคำถามของฉันเองได้ ฉันเพิ่มกลุ่มตัวเลือกเพื่อจับคู่ตัวเลขโรมัน (ซึ่งจะได้รับตัวอักษรตัวใหญ่) นี่คือ regex ที่สมบูรณ์ที่ฉันใช้ตอนนี้: (? <= \ b (?: mc | mac)?) [a-zA-Z] (? <! 's \ b) (?: ii | iii | iv | วี | vi | vii | viii | ix)?
Matt

กรณีของคุณเป็นแบบพิเศษ regex ในคำตอบจะถือว่าแต่ละชื่อ (นามสกุล) เป็นคำที่แยกได้ในสตริงอินพุต (สตริงอินพุตทดสอบมีหลายชื่อ) ดังนั้นจึงไม่มีแนวคิดของ 'end of the name' . หากคุณปฏิบัติต่อสายเข้าเป็นชื่อเดียวที่คุณสามารถคำนำหน้า regex ด้วยเงื่อนไขที่ง่ายในการจัดการกับกรณีของคุณ: เพื่อให้คุณมี\b[ivxlcdm]+$| \b[ivxlcdm]+$|(?<=\b(?:mc|mac)?)[a-zA-Z](?<!'s\b)มันจะทำให้คำที่ลงท้ายด้วยชื่อมีรูปแบบตัวเลขโรมันที่ไม่เข้มงวด ( ivxlcdm) คุณอาจมีผลลัพธ์ที่ไม่พึงประสงค์เช่น 'Li' จะกลายเป็น 'LI'
polkduran

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

1
@ Si8 คุณทดสอบมันหรือยัง? Regex.Replace("JOHN DOE".ToLower(), @"(?<=\b(?:mc|mac)?)[a-zA-Z](?<!'s\b)", m => m.Value.ToUpper())
polkduran

7

Mc และ Mac เป็นคำนำหน้านามสกุลทั่วไปทั่วสหรัฐอเมริกาและอื่น ๆ TextInfo.ToTitleCase ไม่ได้จัดการกรณีเหล่านั้นและไม่ควรใช้เพื่อวัตถุประสงค์นี้ นี่คือวิธีที่ฉันทำ:

    public static string ToTitleCase(string str)
    {
        string result = str;
        if (!string.IsNullOrEmpty(str))
        {
            var words = str.Split(' ');
            for (int index = 0; index < words.Length; index++)
            {
                var s = words[index];
                if (s.Length > 0)
                {
                    words[index] = s[0].ToString().ToUpper() + s.Substring(1);
                }
            }
            result = string.Join(" ", words);
        }
        return result;
    }


4

ตัวเลือกที่ตรงที่สุดคือการใช้ฟังก์ชันToTitleCaseที่มีอยู่ใน. NET ซึ่งควรดูแลชื่อส่วนใหญ่ตลอดเวลา ดังที่edgชี้ให้เห็นว่ามีชื่อบางชื่อที่ไม่สามารถใช้งานได้ แต่สิ่งเหล่านี้ค่อนข้างหายากดังนั้นหากคุณไม่ได้กำหนดเป้าหมายวัฒนธรรมที่ชื่อทั่วไปนั้นไม่จำเป็นต้องมีสิ่งที่คุณต้องกังวลมากเกินไป

อย่างไรก็ตามหากคุณไม่ได้ทำงานกับ. NET แล้วก็ขึ้นอยู่กับสิ่งที่ป้อนเข้า - ถ้าคุณมีสองฟิลด์แยกต่างหากสำหรับชื่อและนามสกุลคุณสามารถพิมพ์อักษรตัวแรกที่เหลือโดยใช้อักษรตัวเล็ก สตริง

firstName = firstName.Substring(0, 1).ToUpper() + firstName.Substring(1).ToLower();
lastName = lastName.Substring(0, 1).ToUpper() + lastName.Substring(1).ToLower();

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


3

CultureInfo.CurrentCulture.TextInfo.ToTitleCase ("ชื่อของฉัน");

ส่งกลับ ~ ชื่อของฉัน

แต่ปัญหายังคงมีอยู่กับชื่ออย่าง McFly ตามที่ระบุไว้ก่อนหน้านี้


3
McFry! Konichiwa นาย Fugitsu-san
Ian Boyd

@ David C ลองเปลี่ยนช่องว่างด้วย null !! ชอบ string.replace ('', '')
Chintan

3

ฉันใช้วิธีการของตัวเองเพื่อแก้ไขปัญหานี้:

ตัวอย่างเช่นวลี: "hello world สวัสดีนี่คือโลก stackoverflow" จะเป็น "Hello World สวัสดีนี่คือ The Stackoverflow World" Regex \ b (จุดเริ่มต้นของคำ) \ w (ตัวอักษรแรกของคำ) จะทำเคล็ดลับ

/// <summary>
/// Makes each first letter of a word uppercase. The rest will be lowercase
/// </summary>
/// <param name="Phrase"></param>
/// <returns></returns>
public static string FormatWordsWithFirstCapital(string Phrase)
{
     MatchCollection Matches = Regex.Matches(Phrase, "\\b\\w");
     Phrase = Phrase.ToLower();
     foreach (Match Match in Matches)
         Phrase = Phrase.Remove(Match.Index, 1).Insert(Match.Index, Match.Value.ToUpper());

     return Phrase;
}

2

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


6
ทำไมไม่โทร ToLower บนสายป้อนก่อนโทร ToTitleCase
Andy Rose

2

ชั้นเรียนนี้ใช้กลอุบาย คุณสามารถเพิ่มคำนำหน้าใหม่ให้กับ_prefixesคงที่อาร์เรย์สตริง

public static class StringExtensions
{
        public static string ToProperCase( this string original )
        {
            if( String.IsNullOrEmpty( original ) )
                return original;

            string result = _properNameRx.Replace( original.ToLower( CultureInfo.CurrentCulture ), HandleWord );
            return result;
        }

        public static string WordToProperCase( this string word )
        {
            if( String.IsNullOrEmpty( word ) )
                return word;

            if( word.Length > 1 )
                return Char.ToUpper( word[0], CultureInfo.CurrentCulture ) + word.Substring( 1 );

            return word.ToUpper( CultureInfo.CurrentCulture );
        }

        private static readonly Regex _properNameRx = new Regex( @"\b(\w+)\b" );
        private static readonly string[] _prefixes = {
                                                         "mc"
                                                     };

        private static string HandleWord( Match m )
        {
            string word = m.Groups[1].Value;

            foreach( string prefix in _prefixes )
            {
                if( word.StartsWith( prefix, StringComparison.CurrentCultureIgnoreCase ) )
                    return prefix.WordToProperCase() + word.Substring( prefix.Length ).WordToProperCase();
            }

            return word.WordToProperCase();
        }
}

1

หากคุณใช้ vS2k8 คุณสามารถใช้วิธีการขยายเพื่อเพิ่มเข้าไปในคลาส String ได้:

public static string FirstLetterToUpper(this String input)
{
    return input = input.Substring(0, 1).ToUpper() + 
       input.Substring(1, input.Length - 1);
}

9
Char.ToUpper(input[0]) + input.Substring(1)สามารถอ่านได้มากขึ้น IMHO
Hosam Aly

IMHO input.FirstLetterToUpper()แน่นอนมากขึ้นอ่านเทียบกับChar.ToUpper(input[0]) + input.Substring(1)แต่น้อยโปร่งใส
ไมเคิล

0

หากต้องการปัดเศษปัญหา / ปัญหาที่เน้นไปที่เบ็นฉันขอแนะนำให้แปลงสตริงเป็นตัวพิมพ์เล็กก่อนแล้วจึงเรียกเมธอด ToTitleCase จากนั้นคุณสามารถใช้ IndexOf ("Mc") หรือ IndexOf ("O \ '") เพื่อกำหนดกรณีพิเศษที่ต้องการความสนใจเป็นพิเศษ

inputString = inputString.ToLower();
inputString = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(inputString);
int indexOfMc = inputString.IndexOf(" Mc");
if(indexOfMc  > 0)
{
   inputString.Substring(0, indexOfMc + 3) + inputString[indexOfMc + 3].ToString().ToUpper() + inputString.Substring(indexOfMc + 4);
}

0

ฉันชอบวิธีนี้:

using System.Globalization;
...
TextInfo myTi = new CultureInfo("en-Us",false).TextInfo;
string raw = "THIS IS ALL CAPS";
string firstCapOnly = myTi.ToTitleCase(raw.ToLower());

ยกมาจากนี้บทความ MSDN


0

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

String fName = "firstname";
String lName = "lastname";
String capitalizedFName = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(fName);
String capitalizedLName = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(lName);

0
 public static string ConvertToCaptilize(string input)
        {
            if (!string.IsNullOrEmpty(input))
            {
                string[] arrUserInput = input.Split(' ');


                // Initialize a string builder object for the output
                StringBuilder sbOutPut = new StringBuilder();


                // Loop thru each character in the string array
                foreach (string str in arrUserInput)
                {
                    if (!string.IsNullOrEmpty(str))
                    {
                        var charArray = str.ToCharArray();
                        int k = 0;
                        foreach (var cr in charArray)
                        {
                            char c;
                            c = k == 0 ? char.ToUpper(cr) : char.ToLower(cr);
                            sbOutPut.Append(c);
                            k++;
                        }


                    }
                    sbOutPut.Append(" ");
                }
                return sbOutPut.ToString();
            }
            return string.Empty;

        }

-1

เช่นเดียวกับที่ระบุใน edg คุณจะต้องใช้อัลกอริทึมที่ซับซ้อนมากขึ้นในการจัดการชื่อพิเศษ (นี่อาจเป็นเหตุผลว่าทำไมหลาย ๆ ที่บังคับให้ทุกอย่างเป็นตัวใหญ่)

บางอย่างเช่น c # ที่ยังไม่ทดลองนี้ควรจัดการกับกรณีง่าย ๆ ที่คุณร้องขอ:

public string SentenceCase(string input)
{
    return input(0, 1).ToUpper + input.Substring(1).ToLower;
}

ลืมสิ่งนี้ - ใช้ระดับโลกาภิวัฒน์stackoverflow.com/questions/72831/ …
Michael Haren
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.