Bagaimana cara mengubah huruf besar dari nama depan dan nama belakang dalam C #?

141

Apakah ada cara mudah untuk menggunakan huruf besar dari string pertama dan menurunkan sisanya? Apakah ada metode bawaan atau apakah saya perlu membuatnya sendiri?

Mike Roosa
sumber
3
Saya tidak tahu apa-apa tentang aplikasi khusus Anda, tetapi saya pikir peringatan umum adalah karena: programmer tidak boleh menerapkan metode ini mau tak mau untuk nama asli. Saya pikir tua John MacDonald akan marah metode ini mengacaukan namanya, belum lagi ee cummings, kait bel, danah boyd, 松本 行 弘, orang-orang dengan "von" di nama belakang, orang-orang dengan nama belakang "O'Doyle" , dll., dll., dll. Sebagian besar nama bukan dari format "First Last" dengan huruf besar itu (dan dalam huruf kapital); Saya sarankan membaca kalzumeus.com/2010/06/17/...
Nick
@Nick benar sekali. Anda bahkan tidak dapat berasumsi bahwa huruf kecil diikuti oleh huruf besar salah - nama Irlandia melakukan hal-hal seperti "Ó hAirt". Asumsikan bahwa untuk konvensi apa pun yang dapat Anda pikirkan, ada budaya / bahasa yang akan mengejutkan Anda.
James Moore

Jawaban:

259

TextInfo.ToTitleCase()mengkapitalkan karakter pertama dalam setiap token string.
Jika tidak perlu mempertahankan Acronym Uppercasing, maka Anda harus memasukkan ToLower().

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

Jika CurrentCulture tidak tersedia, gunakan:

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

Lihat Tautan MSDN untuk deskripsi terperinci.

ageektrapped
sumber
24
Satu hal yang perlu diperhatikan di sini adalah bahwa itu tidak berfungsi jika string adalah huruf besar semua. Ia berpikir bahwa semua topi adalah akronim.
Mike Roosa
9
Hal yang saya lihat dengan banyak di antaranya adalah Anda tidak bisa mengandalkan mereka. Ini tidak akan berhasil jika namanya mirip dengan McCain atau jika Anda mulai memukul lebih banyak nama asing.
Mike Wills
25
@roosa - perbaikan mudah untuk ToTitleCase (val.ToLower ())
Simon_Weaver
+1 Saya tahu itu harus sudah ada di FCL, dan google membawa saya ke sini = D
gideon
13
Tidak seperti jawaban Nathan di bawah ini, saya mendapatkan kesalahan: "Referensi objek diperlukan untuk bidang non-statis, metode, atau properti ......." sayangnya.
Dan W
117
CultureInfo.CurrentCulture.TextInfo.ToTitleCase("hello world");
Nathan Baulch
sumber
Aww snap! Jawaban yang bagus. Saya selalu melupakan hal-hal globalisasi.
Michael Haren
Solusi bagus! Dalam VB.Net:sItem = Globalization.CultureInfo.CurrentCulture.TextInfo.ToTitleCase(sItem.ToLower) 'first char upper case
Nasenbaer
Anda perlu mendeteksi budaya setiap nama individu , bukan budaya saat ini. Ini tidak berfungsi untuk nama.
James Moore
1
Karena ini bergantung pada CurrentCulture, bagaimana kita bisa yakin bahwa tidak ada budaya yang menangani hal ini secara berbeda?
Rudey
30
String test = "HELLO HOW ARE YOU";
string s = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(test);

Kode di atas tidak akan berfungsi .....

jadi letakkan kode di bawah ini dengan mengkonversi ke bawah lalu menerapkan fungsi

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

Ada beberapa kasus yang CultureInfo.CurrentCulture.TextInfo.ToTitleCasetidak bisa ditangani, misalnya: apostrof '.

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

Sebuah regex juga dapat digunakan \b[a-zA-Z]untuk mengidentifikasi karakter mulai dari sebuah kata setelah batas kata \b, maka kita perlu hanya untuk mengganti pertandingan dengan kasus kesetaraan nya berkat atas ke Regex.Replace(string input,string pattern,MatchEvaluator evaluator)metode:

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

The regex dapat disetel jika diperlukan, misalnya, jika kita ingin menangani MacDonalddan McFrykasus regex menjadi:(?<=\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

Jika kita perlu menangani lebih prefiks kita hanya perlu memodifikasi kelompok (?:mc|mac), misalnya untuk menambahkan prefiks Prancis du, de: (?:mc|mac|du|de).

Akhirnya, kita dapat menyadari bahwa regex ini juga akan cocok dengan case MacDonald'Suntuk yang terakhir 'ssehingga kita harus menanganinya di regex dengan tampilan negatif di belakang (?<!'s\b). Pada akhirnya kami memiliki:

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
sumber
@polkduran Saya berjuang untuk menemukan cara untuk berurusan dengan angka romawi di akhir nama; Saya ingin membuat semuanya huruf besar: John Smith III. Apakah pandangan negatif akan mengganggu ini?
Matt
Seperti biasanya, saya akhirnya bisa menjawab pertanyaan saya sendiri. Saya menambahkan grup opsional untuk mencocokkan angka romawi (yang akan menjadi huruf besar). Inilah regex lengkap yang saya gunakan sekarang: (? <= \ B (?: Mc | mac)?) [A-zA-Z] (? <! 'S \ b) (?: ii | iii | iv | v | vi | vii | viii | ix)?
Matt
Kasing Anda adalah kasus khusus, regex dalam jawaban memperlakukan setiap nama (nama belakang) sebagai kata yang terisolasi dalam string input (string input tes memiliki beberapa nama) sehingga tidak memiliki gagasan 'akhir nama' . Jika Anda memperlakukan string input sebagai nama tunggal, Anda dapat mengawali regex dengan kondisi sederhana untuk menangani kasus Anda: \b[ivxlcdm]+$|begitulah \b[ivxlcdm]+$|(?<=\b(?:mc|mac)?)[a-zA-Z](?<!'s\b). Ini akan membuat upercase semua kata penutup dari nama yang memiliki format angka romawi yang tidak ketat ( ivxlcdm). Namun Anda mungkin memiliki beberapa hasil yang tidak diinginkan, misalnya 'Li' akan menjadi 'LI'
polkduran
Menarik. Saya pikir penambahan Anda mungkin lebih benar mengenai struktur, tapi saya setuju ... Saya pikir akan ada beberapa masalah yang Anda nyatakan. Dalam solusi saya di atas, saya mengkodekan sufiks hingga "ix" yang akan berfungsi dalam kasus saya tetapi saya tahu mungkin tidak cocok untuk semua orang.
Matt
1
@ Si8, sudahkah Anda mengujinya? Regex.Replace("JOHN DOE".ToLower(), @"(?<=\b(?:mc|mac)?)[a-zA-Z](?<!'s\b)", m => m.Value.ToUpper())
polkduran
7

Mc dan Mac adalah awalan nama keluarga umum di seluruh AS, dan ada yang lainnya. TextInfo.ToTitleCase tidak menangani kasus tersebut dan tidak boleh digunakan untuk tujuan ini. Begini cara saya melakukannya:

    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;
    }
Ide Jamie
sumber
4

Opsi yang paling langsung adalah menggunakan fungsi ToTitleCase yang tersedia di .NET yang seharusnya menangani sebagian besar nama. Seperti yang ditunjukkan edg ada beberapa nama yang tidak akan berhasil, tetapi ini cukup langka jadi kecuali Anda menargetkan budaya di mana nama-nama seperti itu umum, tidak perlu sesuatu yang harus Anda khawatirkan terlalu banyak.

Namun jika Anda tidak bekerja dengan langauge .NET, maka itu tergantung pada apa yang tampak seperti input - jika Anda memiliki dua bidang terpisah untuk nama depan dan nama belakang maka Anda bisa menggunakan huruf besar huruf pertama dan sisanya dengan menggunakan substring.

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

Namun, jika Anda diberikan beberapa nama sebagai bagian dari string yang sama maka Anda perlu tahu bagaimana Anda mendapatkan informasi dan membaginya sesuai. Jadi jika Anda mendapatkan nama seperti "John Doe" Anda membagi string berdasarkan karakter ruang. Jika dalam format seperti "Doe, John" Anda harus membaginya berdasarkan koma. Namun, setelah Anda membaginya, Anda hanya menerapkan kode yang ditunjukkan sebelumnya.

rjzii
sumber
3

CultureInfo.CurrentCulture.TextInfo.ToTitleCase ("nama saya");

kembali ~ Nama Saya

Tapi masalahnya masih ada dengan nama-nama seperti McFly seperti yang dinyatakan sebelumnya.

David C
sumber
3
McFry! Konichiwa, Tn. Fugitsu-san
Ian Boyd
@ David C Mencoba mengganti ruang dengan nol !! seperti string.replace ('', '')
Chintan
3

Saya menggunakan metode saya sendiri untuk memperbaikinya:

Misalnya ungkapan: "Halo dunia. Halo ini adalah dunia stackoverflow." akan menjadi "Hello World. Hello This Is The Stackoverflow World.". Regex \ b (awal kata) \ w (karakter pertama kata) akan melakukan trik.

/// <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;
}
Ton Snoei
sumber
2

Saran untuk menggunakan ToTitleCase tidak akan berfungsi untuk string yang semuanya huruf besar. Jadi, Anda harus memanggil ToUpper pada char pertama dan ToLower pada karakter yang tersisa.

Tundey
sumber
6
Mengapa tidak memanggil ToLower pada string input sebelum memanggil ToTitleCase?
Andy Rose
2

Kelas ini berhasil. Anda dapat menambahkan awalan baru ke array string statis _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();
        }
}
Eddie Velasquez
sumber
1

Jika Anda menggunakan vS2k8, Anda bisa menggunakan metode ekstensi untuk menambahkannya ke kelas String:

public static string FirstLetterToUpper(this String input)
{
    return input = input.Substring(0, 1).ToUpper() + 
       input.Substring(1, input.Length - 1);
}
FlySwat
sumber
9
Char.ToUpper(input[0]) + input.Substring(1)IMHO lebih mudah dibaca.
Hosam Aly
IMHO input.FirstLetterToUpper()tentu saja lebih mudah dibaca vs Char.ToUpper(input[0]) + input.Substring(1), tetapi kurang transparan
Michael
0

Untuk menyelesaikan beberapa masalah / masalah yang telah saya soroti, saya sarankan untuk mengubah string menjadi huruf kecil terlebih dahulu dan kemudian memanggil metode ToTitleCase. Anda kemudian dapat menggunakan IndexOf ("Mc") atau IndexOf ("O \ '") untuk menentukan kasus khusus yang memerlukan perhatian lebih khusus.

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);
}
Andy Rose
sumber
0

Saya suka seperti ini:

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

Diangkat dari artikel MSDN ini .

TrentVB
sumber
0

Semoga ini bisa membantu Anda.

String fName = "firstname";
String lName = "lastname";
String capitalizedFName = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(fName);
String capitalizedLName = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(lName);
Arun
sumber
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;

        }
Govind Singh Rawat
sumber
-1

Seperti yang ditunjukkan edg, Anda akan memerlukan algoritma yang lebih kompleks untuk menangani nama-nama khusus (ini mungkin mengapa banyak tempat memaksakan segalanya untuk huruf besar).

Sesuatu seperti c # yang belum diuji ini harus menangani kasus sederhana yang Anda minta:

public string SentenceCase(string input)
{
    return input(0, 1).ToUpper + input.Substring(1).ToLower;
}
Michael Haren
sumber
Lupakan ini - gunakan kelas globalisasi stackoverflow.com/questions/72831/…
Michael Haren