¿Cómo escribo con mayúscula la primera letra del nombre y el apellido en C #?

141

¿Hay alguna manera fácil de poner en mayúscula la primera letra de una cadena y bajar el resto? ¿Existe un método incorporado o necesito hacer el mío?

Mike Roosa
fuente
3
No sé nada acerca de su aplicación en particular, pero creo que se debe presentar una advertencia general: los programadores no deberían aplicar este método de forma involuntaria a nombres reales. Creo que el viejo John MacDonald estaría molesto con este método que destroza su nombre, sin mencionar ee cummings, bell hooks, danah boyd, 松本 行 弘, personas con un "von" en el apellido, personas con el apellido "O'Doyle" , etc., etc., etc. La mayoría de los nombres no tienen el formato "Primero Último" con esa mayúscula (y en mayúsculas); Recomiendo leer kalzumeus.com/2010/06/17/…
Nick
@ Nick tiene toda la razón. Ni siquiera puede suponer que las minúsculas seguidas de las mayúsculas están mal: los nombres irlandeses hacen cosas como "Ó hAirt". Suponga que para cualquier convención que se le ocurra, habrá una cultura / idioma que lo sorprenderá.
James Moore

Respuestas:

259

TextInfo.ToTitleCase()capitaliza el primer carácter en cada ficha de una cadena.
Si no es necesario mantener las siglas en mayúsculas, entonces debe incluir ToLower().

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

Si CurrentCulture no está disponible, use:

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

Consulte el enlace de MSDN para obtener una descripción detallada.

ageektrapped
fuente
24
Una cosa a tener en cuenta aquí es que no funciona si la cadena es todo en mayúsculas. Piensa que todo en mayúsculas es un acrónimo.
Mike Roosa
9
Lo que he visto con muchos de estos es que no puedes confiar en ellos. No funcionaría si el nombre es algo así como McCain o si comienzas a usar más nombres extranjeros.
Mike Wills
25
@roosa - solución fácil para ese ToTitleCase (val.ToLower ())
Simon_Weaver
+1 Sabía que ya tenía que estar en la FCL, y Google me trajo aquí = D
gideon
13
A diferencia de la respuesta de Nathan a continuación, aparece un error: "Se necesita una referencia de objeto para el campo, método o propiedad no estático ......." desafortunadamente.
Dan W
117
CultureInfo.CurrentCulture.TextInfo.ToTitleCase("hello world");
Nathan Baulch
fuente
Aww snap! Buena respuesta. Siempre me olvido de las cosas de la globalización.
Michael Haren
Gran solución! En VB.Net:sItem = Globalization.CultureInfo.CurrentCulture.TextInfo.ToTitleCase(sItem.ToLower) 'first char upper case
Nasenbaer
Debe detectar la cultura de cada nombre individual , no la cultura actual. Esto no funciona para los nombres.
James Moore
1
Dado que esto se basa en CurrentCulture, ¿cómo podemos estar seguros de que no hay una cultura que maneje esto de manera diferente?
Rudey
30
String test = "HELLO HOW ARE YOU";
string s = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(test);

El código anterior no funcionará .....

así que pon el siguiente código convirtiendo a inferior y luego aplica la función

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

Hay algunos casos que CultureInfo.CurrentCulture.TextInfo.ToTitleCaseno pueden manejar, por ejemplo: el apóstrofe '.

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

Una expresión regular también se puede usar \b[a-zA-Z]para identificar el carácter inicial de una palabra después del límite de una palabra \b, entonces solo necesitamos reemplazar la coincidencia por su equivalencia en mayúsculas gracias al Regex.Replace(string input,string pattern,MatchEvaluator evaluator)método:

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

La expresión regular se puede ajustar si es necesario, por ejemplo, si queremos manejar los casos MacDonaldy McFryla expresión regular se convierte en:(?<=\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

Si tenemos que manejar más prefijos sólo tenemos que modificar el grupo (?:mc|mac), por ejemplo, para añadir prefijos francés du, de: (?:mc|mac|du|de).

Finalmente, podemos darnos cuenta de que esta expresión regular también coincidirá con el caso MacDonald'Spara el último, 'spor lo que debemos manejarla en la expresión regular con una mirada negativa hacia atrás (?<!'s\b). Al final tenemos:

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
fuente
@polkduran Estoy luchando por encontrar una manera de lidiar con los números romanos al final del nombre; Me gustaría ponerlos en mayúscula: John Smith III. ¿La observación negativa interferiría con esto?
Matt
Como suele suceder, finalmente pude responder mi propia pregunta. Agregué un grupo opcional para que coincida con los números romanos (que serán mayúsculas). Aquí está la expresión regular completa que estoy usando ahora: (? <= \ B (?: Mc | mac)?) [A-zA-Z] (? <! 'S \ b) (?: ii | iii | iv | v | vi | vii | viii | ix)?
Matt
Su caso es especial, la expresión regular en la respuesta trata cada nombre (apellido) como una palabra aislada en la cadena de entrada (la cadena de entrada de prueba tiene varios nombres) por lo que no tiene la noción de 'fin del nombre' . Si trata la cadena de entrada como un solo nombre, puede prefijar la expresión regular con una condición simple para tratar su caso: \b[ivxlcdm]+$|así es \b[ivxlcdm]+$|(?<=\b(?:mc|mac)?)[a-zA-Z](?<!'s\b). Hará mayúsculas todas las palabras finales de un nombre que tenga un formato de número romano no estricto ( ivxlcdm). Sin embargo, puede tener algunos resultados no deseados, por ejemplo, 'Li' se convertirá en 'LI'
polkduran 03 de
Interesante. Creo que su adición es probablemente más correcta con respecto a la estructura, pero estoy de acuerdo ... Creo que habrá algunos problemas que usted indicó. En mi solución anterior, codifiqué los sufijos hasta "ix", lo que funcionará en mi caso, pero reconozco que puede no ser adecuado para todos.
Matt
1
@ Si8, ¿lo has probado? Regex.Replace("JOHN DOE".ToLower(), @"(?<=\b(?:mc|mac)?)[a-zA-Z](?<!'s\b)", m => m.Value.ToUpper())
polkduran
7

Mc y Mac son prefijos de apellidos comunes en todo EE. UU., Y hay otros. TextInfo.ToTitleCase no maneja esos casos y no debe usarse para este propósito. Así es como lo estoy haciendo:

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

La opción más directa será utilizar la función ToTitleCase que está disponible en .NET, que debería ocuparse del nombre la mayor parte del tiempo. Como señaló Edg , hay algunos nombres para los que no funcionará, pero estos son bastante raros, por lo que, a menos que se dirija a una cultura donde tales nombres son comunes, no es necesario algo de lo que deba preocuparse demasiado.

Sin embargo, si no está trabajando con un lenguaje .NET, entonces depende de cómo se vea la entrada; si tiene dos campos separados para el nombre y el apellido, entonces puede poner en mayúscula la primera letra más abajo usando el resto. subcadenas.

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

Sin embargo, si se le proporcionan varios nombres como parte de la misma cadena, entonces necesita saber cómo está obteniendo la información y dividirla en consecuencia. Entonces, si obtiene un nombre como "John Doe", puede dividir la cadena en función del carácter de espacio. Si está en un formato como "Doe, John", deberá dividirlo según la coma. Sin embargo, una vez que lo haya dividido, simplemente aplique el código que se mostró anteriormente.

rjzii
fuente
3

CultureInfo.CurrentCulture.TextInfo.ToTitleCase ("mi nombre");

devuelve ~ Mi nombre

Pero el problema aún existe con nombres como McFly como se indicó anteriormente.

David C
fuente
3
McFry! Konichiwa, Sr. Fugitsu-san
Ian Boyd
@David C ¡Intenta reemplazar el espacio con nulo! like string.replace ('', '')
Chintan
3

Yo uso mi propio método para arreglar esto:

Por ejemplo, la frase: "hola mundo. Hola, este es el mundo de stackoverflow". será "Hola mundo. Hola, este es el mundo de Stackoverflow". Regex \ b (comienzo de una palabra) \ w (primer personaje de la palabra) hará el truco.

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

Las sugerencias para usar ToTitleCase no funcionarán para cadenas que están en mayúsculas. Entonces tendrás que llamar a ToUpper en el primer personaje y a ToLower en los personajes restantes.

Tundey
fuente
66
¿Por qué no llamar a ToLower en la cadena de entrada antes de llamar a ToTitleCase?
Andy Rose
2

Esta clase hace el truco. Puede agregar nuevos prefijos a la matriz de cadenas estáticas _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
fuente
1

Si usa vS2k8, puede usar un método de extensión para agregarlo a la clase String:

public static string FirstLetterToUpper(this String input)
{
    return input = input.Substring(0, 1).ToUpper() + 
       input.Substring(1, input.Length - 1);
}
FlySwat
fuente
9
Char.ToUpper(input[0]) + input.Substring(1)es más legible en mi humilde opinión.
Hosam Aly
En mi humilde opinión input.FirstLetterToUpper()es ciertamente más legible frente Char.ToUpper(input[0]) + input.Substring(1), pero menos transparente
Michael
0

Para resolver algunos de los problemas / problemas que se han destacado, sugeriría convertir primero la cadena a minúscula y luego llamar al método ToTitleCase. Luego puede usar IndexOf ("Mc") o IndexOf ("O \ '") para determinar casos especiales que requieren atención más específica.

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
fuente
0

Me gusta de esta manera:

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

Retirado de este artículo de MSDN .

TrentVB
fuente
0

Espero que esto te ayude.

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

Como se indica en edg, necesitará un algoritmo más complejo para manejar nombres especiales (esta es probablemente la razón por la cual muchos lugares fuerzan todo a mayúsculas).

Algo como esto no probado c # debería manejar el caso simple que solicitó:

public string SentenceCase(string input)
{
    return input(0, 1).ToUpper + input.Substring(1).ToLower;
}
Michael Haren
fuente
Olvídese de esto: use la clase de globalización stackoverflow.com/questions/72831/…
Michael Haren