Convierta todas las primeras letras a mayúsculas, descanse más abajo para cada palabra

110

Tengo una cadena de texto (alrededor de 5-6 palabras en su mayoría) que necesito convertir.

Actualmente el texto se ve así:

THIS IS MY TEXT RIGHT NOW

Quiero convertirlo a:

This Is My Text Right Now

Puedo recorrer mi colección de cadenas, pero no estoy seguro de cómo realizar esta modificación de texto.

mrblah
fuente

Respuestas:

251
string s = "THIS IS MY TEXT RIGHT NOW";

s = System.Threading.Thread.CurrentThread.CurrentCulture.TextInfo.ToTitleCase(s.ToLower());
jspcal
fuente
31
¿Jajaja de verdad? ¿Ahí es donde está? Me encanta .NET, pero algunos de los diseñadores de API son unos idiotas.
George Mauer
7
Tenga en cuenta que, si bien este método hará lo que le pidió el interlocutor, es un algoritmo ingenuo que solo escribe en mayúscula cada palabra, sin importar qué tipo de palabra sea. En realidad, no se trata de "mayúsculas y minúsculas", ya que las reglas para las mayúsculas y minúsculas del título difieren en diferentes idiomas. Ni siquiera es correcto para el inglés. Por ejemplo, el título "sobre un niño" debería ser "Acerca de un niño" en inglés, pero este método daría "Acerca de un niño". Si quieres un título verdadero , tendrás que escribir tu propio método.
Ryan Lundy
18
No los llamaría idiotas. El problema con "ToTitleCase" es que depende de la cultura, por lo que tiene que estar en el espacio de nombres System.Globalization. Pasar por CurrentThread solo se realiza para obtener la cultura actual del hilo (¡tenga en cuenta que esto puede causar un comportamiento diferente si el usuario tiene una configuración regional diferente!). También podría hacer "CultureInfo.InvariantCulture.TextInfo.ToTitleCase ()", que puede ser mejor ya que InvariantCulture se comporta igual en todas las culturas. George: ¿Dónde colocaría una función de cadena específica de la cultura?
Michael Stum
3
También tenga en cuenta los comentarios sobre TODAS las cadenas en MAYÚSCULAS: msdn.microsoft.com/en-us/library/…
Michael Stum
2
el método toLower () debe ser ToLower (), la primera letra del método comienza con mayúsculas
Alex
84

Probablemente prefiera invocar ToTitleCase de CultureInfo ( System.Globalization ) que Thread.CurrentThread ( System.Threading )

string s = "THIS IS MY TEXT RIGHT NOW";
s = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(s.ToLower());

pero debería ser lo mismo que la solución jspcal

EDITAR

En realidad, esas soluciones no son las mismas : CurrentThread--llama -> CultureInfo!


System.Threading.Thread.CurrentThread.CurrentCulture

string s = "THIS IS MY TEXT RIGHT NOW";
s = System.Threading.Thread.CurrentThread.CurrentCulture.TextInfo.ToTitleCase(s.ToLower());

IL_0000:  ldstr       "THIS IS MY TEXT RIGHT NOW"
IL_0005:  stloc.0     // s
IL_0006:  call        System.Threading.Thread.get_CurrentThread
IL_000B:  callvirt    System.Threading.Thread.get_CurrentCulture
IL_0010:  callvirt    System.Globalization.CultureInfo.get_TextInfo
IL_0015:  ldloc.0     // s
IL_0016:  callvirt    System.String.ToLower
IL_001B:  callvirt    System.Globalization.TextInfo.ToTitleCase
IL_0020:  stloc.0     // s

System.Globalization.CultureInfo.CurrentCulture

string s = "THIS IS MY TEXT RIGHT NOW";
s = System.Globalization.CultureInfo.CurrentCulture.TextInfo.ToTitleCase(s.ToLower());

IL_0000:  ldstr       "THIS IS MY TEXT RIGHT NOW"
IL_0005:  stloc.0     // s
IL_0006:  call        System.Globalization.CultureInfo.get_CurrentCulture
IL_000B:  callvirt    System.Globalization.CultureInfo.get_TextInfo
IL_0010:  ldloc.0     // s
IL_0011:  callvirt    System.String.ToLower
IL_0016:  callvirt    System.Globalization.TextInfo.ToTitleCase
IL_001B:  stloc.0     // s

Referencias:

Filippo Vitale
fuente
16

Hay un par de formas de convertir el primer carácter de una cadena a mayúsculas.

La primera forma es crear un método que simplemente limite el primer carácter y agregue el resto de la cadena usando una subcadena:

public string UppercaseFirst(string s)
    {
        return char.ToUpper(s[0]) + s.Substring(1);
    }

La segunda forma (que es un poco más rápida) es dividir la cadena en una matriz de caracteres y luego reconstruir la cadena:

public string UppercaseFirst(string s)
    {
        char[] a = s.ToCharArray();
        a[0] = char.ToUpper(a[0]);
        return new string(a);
    }
Jamie Dixon
fuente
1
Esta solución no responde exactamente a la pregunta de manera adecuada. El título de la pregunta es "Convertir todas las primeras letras a mayúsculas, el resto en minúsculas para cada palabra". Sin embargo, esta solución solo escribe en mayúscula la primera letra de toda la cadena. Por lo tanto, esta solución convertiría "hola mundo" en "hola mundo", en lugar de "hola mundo".
brsfan
9

No probado, pero algo como esto debería funcionar:

var phrase = "THIS IS MY TEXT RIGHT NOW";
var rx = new System.Text.RegularExpressions.Regex(@"(?<=\w)\w");
var newString = rx.Replace(phrase,new MatchEvaluator(m=>m.Value.ToLowerInvariant()));

Básicamente, dice "preformar una coincidencia de expresiones regulares en todas las apariciones de un carácter alfanumérico que siga a otro carácter alfanumérico y luego reemplazarlo con una versión en minúscula de sí mismo".

George Mauer
fuente
Este también hace que todas las palabras en mayúsculas comiencen con mayúsculas y continúen con minúsculas. Exactamente lo que estaba buscando.
M. Azyoksul
9

Si está utilizando en una página web, también puede utilizar CSS:

style="text-transform:capitalize;"

M.Eren Çelik
fuente
2
¿Por qué CSS? Cuando la pregunta es para c # asp.net regex
Jay
1
La etiqueta ASP.NETmuestra que el OP lo está haciendo en WEB. Por supuesto, esta no es la respuesta a la pregunta porque OP requería la solución, C#pero resuelve el problema y puede ser una solución alternativa. +1
Muhammad Saqib
6

Al construir mesas grandes, la velocidad es una preocupación, por lo que la segunda función de Jamie Dixon es la mejor, pero no funciona completamente como está ...

No toma todas las letras en minúsculas, y solo escribe en mayúscula la primera letra de la cadena, no la primera letra de cada palabra en la cadena ... la siguiente opción soluciona ambos problemas:

    public string UppercaseFirstEach(string s)
    {
        char[] a = s.ToLower().ToCharArray();

        for (int i = 0; i < a.Count(); i++ )
        {
            a[i] = i == 0 || a[i-1] == ' ' ? char.ToUpper(a[i]) : a[i];

        }

        return new string(a);
    }

Aunque en este punto, no se sabe si esta sigue siendo la opción más rápida, la Regexsolución proporcionada por George Mauer podría ser más rápida ... alguien que se preocupe lo suficiente debería probarla.

Serj Sagan
fuente
2
funciona, pero cambié este "a.Count ()" a a.Length
Christian
2

No sé si la solución a continuación es más o menos eficiente que la respuesta de jspcal, pero estoy bastante seguro de que requiere menos creación de objetos que la de Jamie y George.

string s = "THIS IS MY TEXT RIGHT NOW";
StringBuilder sb = new StringBuilder(s.Length);
bool capitalize = true;
foreach (char c in s) {
    sb.Append(capitalize ? Char.ToUpper(c) : Char.ToLower(c));
    capitalize = !Char.IsLetter(c);
}
return sb.ToString();
efímero
fuente
1
Si nos preocupa la creación de objetos, ¿por qué no hacerlo en el lugar con una indexación de bucle for sobre s en lugar de usar un StringBuilder?
jball
0

Además de la primera respuesta, recuerde cambiar el índice de inicio de selección de cadena al final de la palabra o obtendrá el orden inverso de las letras en la cadena.

s.SelectionStart=s.Length;
zia khan
fuente
0

Pruebe esta técnica; Devuelve el resultado deseado

CultureInfo.CurrentCulture.TextInfo.ToTitleCase(str.ToLower());

Y no olvides usar System.Globalization.

Beyondo
fuente
0

Una de las posibles soluciones que podría interesarle. Atravesar una matriz de caracteres de derecha a izquierda y viceversa en un bucle.

public static string WordsToCapitalLetter(string value)
    {
        if (string.IsNullOrWhiteSpace(value))
        {
            throw new ArgumentException("value");
        }

        int inputValueCharLength = value.Length;
        var valueAsCharArray = value.ToCharArray();

        int min = 0;
        int max = inputValueCharLength - 1;

        while (max > min)
        {
            char left = value[min];
            char previousLeft = (min == 0) ? left : value[min - 1];

            char right = value[max];
            char nextRight = (max == inputValueCharLength - 1) ? right : value[max - 1];

            if (char.IsLetter(left) && !char.IsUpper(left) && char.IsWhiteSpace(previousLeft))
            {
                valueAsCharArray[min] = char.ToUpper(left);
            }

            if (char.IsLetter(right) && !char.IsUpper(right) && char.IsWhiteSpace(nextRight))
            {
                valueAsCharArray[max] = char.ToUpper(right);
            }

            min++;
            max--;
        }

        return new string(valueAsCharArray);
    }
RShp
fuente
0

La respuesta de jspcal como una extensión de cadena.

Program.cs

class Program
{
    static void Main(string[] args)
    {
        var myText = "MYTEXT";
        Console.WriteLine(myText.ToTitleCase()); //Mytext
    }
}

StringExtensions.cs

using System;
public static class StringExtensions
{

    public static string ToTitleCase(this string str)
    {
        if (str == null)
            return null;

        return System.Threading.Thread.CurrentThread.CurrentCulture.TextInfo.ToTitleCase(str.ToLower());
    }
}
Joel Wiklund
fuente