Làm cách nào để viết hoa chữ cái đầu của tên và họ trong C #?


141

Có một cách dễ dàng để viết hoa chữ cái đầu tiên của chuỗi và hạ thấp phần còn lại của chuỗi không? Có một phương pháp được xây dựng trong hoặc tôi cần phải làm cho riêng mình?


3
Tôi không biết gì về ứng dụng cụ thể của bạn, nhưng tôi nghĩ rằng một cảnh báo chung là do: các lập trình viên không nên áp dụng phương pháp này với tên thật. Tôi nghĩ rằng John MacDonald cũ sẽ buồn bã phương pháp này xáo trộn tên của anh ấy, không kể đến ee cummings, chuông hook, danah boyd, 松本 行, những người có "von" trong tên cuối cùng, những người có tên cuối cùng là "O'Doyle" , v.v., v.v ... Hầu hết các tên không có định dạng "Đầu tiên cuối cùng" với chữ viết hoa đó (và bằng các ký tự viết hoa); Tôi khuyên bạn nên đọc kalzumeus.com/2010/06/17/u
Nick

@Nick là hoàn toàn đúng. Bạn thậm chí không thể cho rằng chữ thường theo sau chữ hoa là sai - tên Ailen làm những việc như "Ó hAirt". Giả sử rằng đối với bất kỳ quy ước nào bạn có thể nghĩ ra khỏi đỉnh đầu của bạn, sẽ có một văn hóa / ngôn ngữ sẽ làm bạn ngạc nhiên.
James Moore

Câu trả lời:


259

TextInfo.ToTitleCase()viết hoa ký tự đầu tiên trong mỗi mã thông báo của chuỗi.
Nếu không có nhu cầu duy trì viết tắt Acronym, thì bạn nên bao gồm ToLower().

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

Nếu CurrentCARM không khả dụng, hãy sử dụng:

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

Xem Liên kết MSDN để biết mô tả chi tiết.


24
Một điều cần lưu ý ở đây là nó không hoạt động nếu chuỗi là tất cả chữ hoa. Nó nghĩ rằng tất cả các mũ là một từ viết tắt.
Mike Roosa

9
Điều tôi đã thấy với nhiều trong số này là bạn không thể dựa vào chúng. Nó sẽ không hoạt động nếu tên đó là một cái gì đó giống như McCain hoặc nếu bạn bắt đầu đánh nhiều tên nước ngoài hơn.
Mike sẽ làm việc vào

25
@roosa - sửa lỗi dễ dàng cho ToTitleCase đó (val.ToLower ())
Simon_Weaver

+1 Tôi biết rằng nó phải có trong FCL và google đã đưa tôi đến đây = D
gideon

13
Không giống như câu trả lời của Nathan bên dưới, tôi gặp lỗi: "Không cần tham chiếu đối tượng cho trường không tĩnh, phương thức hoặc thuộc tính .......".
Dan W

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

Aww chụp nhanh! Câu trả lời tốt. Tôi luôn quên những thứ toàn cầu hóa.
Michael Haren

Giải pháp tuyệt vời! Trong VB.Net:sItem = Globalization.CultureInfo.CurrentCulture.TextInfo.ToTitleCase(sItem.ToLower) 'first char upper case
Nasenbaer

Bạn cần phát hiện văn hóa của từng tên riêng lẻ , không phải văn hóa hiện tại. Điều này không làm việc cho tên.
James Moore

1
Vì điều này phụ thuộc vào CurrentCulture, làm thế nào chúng ta có thể chắc chắn rằng không có văn hóa nào xử lý việc này khác nhau?
Rudey

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

Các mã trên sẽ không hoạt động .....

Vì vậy, đặt mã dưới đây bằng cách chuyển đổi để thấp hơn sau đó áp dụng chức năng

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

15

Có một số trường hợp CultureInfo.CurrentCulture.TextInfo.ToTitleCasekhông thể xử lý, ví dụ: dấu nháy đơn '.

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

Một regex cũng có thể được sử dụng \b[a-zA-Z]để xác định ký tự bắt đầu của một từ sau một ranh giới từ \b, sau đó chúng ta chỉ cần thay thế từ khớp bằng chữ hoa của nó nhờ Regex.Replace(string input,string pattern,MatchEvaluator evaluator)phương thức:

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

Các regex có thể được điều chỉnh nếu cần thiết, ví dụ, nếu chúng ta muốn xử lý MacDonaldMcFrycác trường hợp regex trở thành:(?<=\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

Nếu chúng ta cần xử lý nhiều tiền tố hơn, chúng ta chỉ cần sửa đổi nhóm (?:mc|mac), ví dụ để thêm tiền tố tiếng Pháp du, de:(?:mc|mac|du|de) .

Cuối cùng, chúng ta có thể nhận ra rằng regex này cũng sẽ khớp với trường hợp MacDonald'Scuối cùng 'svì vậy chúng ta cần xử lý nó trong regex với một cái nhìn tiêu cực phía sau (?<!'s\b). Cuối cùng, chúng ta có:

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 Tôi đang vật lộn để tìm cách đối phó với các chữ số La Mã ở cuối tên; Tôi muốn làm cho tất cả chữ hoa: John Smith III. Cái nhìn tiêu cực sẽ can thiệp vào điều này?
Matt

Như thường lệ, cuối cùng tôi đã có thể trả lời câu hỏi của riêng mình. Tôi đã thêm một nhóm tùy chọn để khớp với các chữ số La Mã (sẽ có chữ hoa). Đây là regex hoàn chỉnh mà tôi đang sử dụng ngay bây giờ: (? <= \ B (?: Mc | mac)?) [A-zA-Z] (? <! 'S \ b) (?: Ii | iii | iv | v | vi | vii | viii | ix)?
Matt

Trường hợp của bạn là một trường hợp đặc biệt, biểu thức chính trong câu trả lời coi mỗi tên (họ) là một từ riêng biệt trong chuỗi đầu vào (chuỗi đầu vào kiểm tra có một số tên) vì vậy nó không có khái niệm 'kết thúc tên' . Nếu bạn coi chuỗi đầu vào là một tên duy nhất, bạn có thể đặt tiền tố regex với một điều kiện đơn giản để xử lý trường hợp của bạn: \b[ivxlcdm]+$|vì vậy bạn có \b[ivxlcdm]+$|(?<=\b(?:mc|mac)?)[a-zA-Z](?<!'s\b). Nó sẽ tạo ra tất cả các từ kết thúc của một tên có định dạng chữ số La Mã không nghiêm ngặt ( ivxlcdm). Tuy nhiên, bạn có thể có một số kết quả không mong muốn, ví dụ 'Li' sẽ trở thành 'LI'
polkduran

Hấp dẫn. Tôi nghĩ rằng sự bổ sung của bạn có lẽ đúng hơn về cấu trúc, nhưng tôi đồng ý ... Tôi nghĩ rằng sẽ có một số vấn đề mà bạn nêu. Trong giải pháp của tôi ở trên, tôi đã mã hóa cứng các hậu tố thành "ix" sẽ hoạt động trong trường hợp của tôi nhưng tôi nhận ra có thể không phù hợp với tất cả mọi người.
Matt

1
@ Si8, bạn đã kiểm tra chưa? Regex.Replace("JOHN DOE".ToLower(), @"(?<=\b(?:mc|mac)?)[a-zA-Z](?<!'s\b)", m => m.Value.ToUpper())
Polkduran

7

Mc và Mac là tiền tố họ phổ biến trên khắp Hoa Kỳ, và có những tiền tố khác. TextInfo.ToTitleCase không xử lý các trường hợp đó và không nên được sử dụng cho mục đích này. Đây là cách tôi đang làm:

    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

Tùy chọn trực tiếp nhất sẽ là sử dụng chức năng ToTitleCase có sẵn trong .NET, phần lớn sẽ đảm nhiệm tên này hầu hết thời gian. Như edg đã chỉ ra rằng có một số tên mà nó sẽ không hoạt động, nhưng chúng khá hiếm vì vậy trừ khi bạn nhắm mục tiêu vào một nền văn hóa nơi những cái tên đó là phổ biến, bạn không phải lo lắng quá nhiều.

Tuy nhiên, nếu bạn không làm việc với ngôn ngữ .NET, thì nó phụ thuộc vào đầu vào trông như thế nào - nếu bạn có hai trường riêng biệt cho tên và họ thì bạn có thể viết hoa chữ cái đầu tiên thấp hơn phần còn lại của nó bằng cách sử dụng chất nền.

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

Tuy nhiên, nếu bạn được cung cấp nhiều tên như một phần của cùng một chuỗi thì bạn cần biết làm thế nào bạn có được thông tin và phân chia nó cho phù hợp. Vì vậy, nếu bạn nhận được một cái tên như "John Doe", bạn hãy tách chuỗi dựa trên ký tự khoảng trắng. Nếu nó ở định dạng như "Doe, John", bạn sẽ cần phải phân tách nó dựa trên dấu phẩy. Tuy nhiên, một khi bạn đã tách nó ra, bạn chỉ cần áp dụng mã được hiển thị trước đó.


3

CultureInfo.CiverseCARM.TextInfo.ToTitleCase ("tên tôi");

trả về ~ Tên tôi

Nhưng vấn đề vẫn tồn tại với những cái tên như McFly như đã nêu trước đó.


3
McFry! Konichiwa, ông Fugitsu-san
Ian Boyd

@David C Hãy thử thay thế không gian bằng null !! như string.replace ('', '')
Chintan

3

Tôi sử dụng phương pháp của riêng tôi để sửa lỗi này:

Ví dụ: cụm từ: "xin chào thế giới. Xin chào, đây là thế giới stackoverflow." sẽ là "Xin chào thế giới. Xin chào đây là thế giới Stackoverflow." Regex \ b (bắt đầu một từ) \ w (ký tự đầu tiên của từ) sẽ thực hiện thủ thuật.

/// <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

Các đề xuất sử dụng ToTitleCase sẽ không hoạt động đối với các chuỗi có chữ hoa. Vì vậy, bạn sẽ phải gọi ToUpper trên char đầu tiên và ToLower trên các ký tự còn lại.


6
Tại sao không gọi ToLower trên chuỗi đầu vào trước khi gọi ToTitleCase?
Andy Rose

2

Lớp học này thực hiện các mẹo. Bạn có thể thêm tiền tố mới vào mảng chuỗi tĩnh _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

Nếu bạn sử dụng vS2k8, bạn có thể sử dụng một phương thức mở rộng để thêm nó vào lớp 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 dễ đọc hơn.
Hosam Aly

IMHO input.FirstLetterToUpper()chắc chắn dễ đọc hơn so với Char.ToUpper(input[0]) + input.Substring(1), nhưng ít minh bạch
Michael

0

Để giải quyết một số vấn đề / vấn đề đã được làm nổi bật, tôi khuyên bạn nên chuyển đổi chuỗi thành chữ thường trước và sau đó gọi phương thức ToTitleCase. Sau đó, bạn có thể sử dụng IndexOf ("Mc") hoặc IndexOf ("O \ '") để xác định các trường hợp đặc biệt cần chú ý cụ thể hơn.

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

Tôi thích cách này:

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

Nâng từ bài viết MSDN này .


0

Hy vọng điều này sẽ giúp bạn.

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

Giống như edg đã chỉ ra, bạn sẽ cần một thuật toán phức tạp hơn để xử lý các tên đặc biệt (đây có thể là lý do tại sao nhiều nơi buộc mọi thứ phải viết hoa).

Một cái gì đó như c # chưa được kiểm tra này sẽ xử lý trường hợp đơn giản mà bạn yêu cầu:

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

Quên điều này - sử dụng lớp stackoverflow.com/questions/72831/ trên
Michael Haren
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.