Converta toda a primeira letra em maiúscula, descanse em baixo para cada palavra

110

Tenho uma sequência de texto (cerca de 5 a 6 palavras, principalmente) que preciso converter.

Atualmente, o texto se parece com:

THIS IS MY TEXT RIGHT NOW

Eu quero convertê-lo para:

This Is My Text Right Now

Posso percorrer minha coleção de strings, mas não tenho certeza de como proceder para realizar essa modificação de texto.

mrblah
fonte

Respostas:

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

s = System.Threading.Thread.CurrentThread.CurrentCulture.TextInfo.ToTitleCase(s.ToLower());
jspcal
fonte
31
Haha sério? É onde está? Eu amo .NET, mas alguns dos designers de API são verdadeiros idiotas.
George Mauer
7
Observe que, embora esse método faça o que o questionador pediu, é um algoritmo ingênuo que apenas coloca cada palavra em maiúscula, independentemente do tipo de palavra. Não é realmente "maiúsculas e minúsculas", pois as regras para maiúsculas e minúsculas diferem em diferentes idiomas. Não é nem correto para o inglês. Por exemplo, o título "sobre um menino" deveria ser "Sobre um menino" em inglês, mas esse método resultaria em "Sobre um menino". Se você deseja uma capitalização verdadeira , terá que escrever seu próprio método.
Ryan Lundy
18
Eu não os chamaria de idiotas. O problema com "ToTitleCase" é que ele depende da cultura, portanto, precisa estar no namespace System.Globalization. Percorrer CurrentThread é feito apenas para obter a cultura atual do thread (esteja ciente de que isso pode causar um comportamento diferente se o usuário tiver um local diferente!). Você também pode fazer "CultureInfo.InvariantCulture.TextInfo.ToTitleCase ()", que pode ser melhor, pois InvariantCulture se comporta da mesma forma em todas as culturas. Sem interesse George: Onde você colocaria uma função String específica da cultura?
Michael Stum
3
Observe também os comentários sobre TODAS as strings em MAIÚSCULAS: msdn.microsoft.com/en-us/library/…
Michael Stum
2
o método toLower () deve ser ToLower (), a primeira letra do método começa com maiúscula
Alex
84

Provavelmente prefiro invocar ToTitleCase de CultureInfo ( System.Globalization ) do que Thread.CurrentThread ( System.Threading )

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

mas deve ser o mesmo que a solução jspcal

EDITAR

Na verdade, essas soluções não são as mesmas : CurrentThread--calls -> 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

Referências:

Filippo Vitale
fonte
16

Existem algumas maneiras de converter o primeiro caractere de uma string em maiúsculas.

A primeira maneira é criar um método que simplesmente cobre o primeiro caractere e anexa o resto da string usando uma substring:

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

A segunda maneira (que é um pouco mais rápida) é dividir a string em uma matriz char e, em seguida, reconstruir a string:

public string UppercaseFirst(string s)
    {
        char[] a = s.ToCharArray();
        a[0] = char.ToUpper(a[0]);
        return new string(a);
    }
Jamie Dixon
fonte
1
Esta solução não responde exatamente à pergunta de forma adequada. O título da pergunta é "Converta todas as primeiras letras em maiúsculas, coloque em baixo para cada palavra". No entanto, esta solução coloca em maiúscula apenas a primeira letra de toda a string. Portanto, essa solução converteria "hello world" em "Hello world", em vez de "Hello World".
brsfan
9

Não testado, mas algo assim deve 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()));

Essencialmente, ele diz "preformar uma correspondência de regex em todas as ocorrências de um caractere alfanumérico que segue outro caractere alfanumérico e, em seguida, substituí-lo por uma versão em minúsculas dele mesmo"

George Mauer
fonte
Este também faz com que todas as palavras em maiúsculas comecem com maiúsculas e continuem com minúsculas. Exatamente o que eu estava procurando.
M. Azyoksul
9

Se estiver usando em uma página da web, você também pode usar CSS:

style="text-transform:capitalize;"

M.Eren Çelik
fonte
2
Por que CSS? Quando a pergunta é sobre c # asp.net regex
Jay
1
A tag ASP.NETmostra que o OP está fazendo isso na WEB. É claro que essa não é a resposta da pergunta porque o OP exigiu a solução, C#mas resolve o problema e pode ser uma solução alternativa. +1
Muhammad Saqib
6

Ao construir grandes mesas, a velocidade é uma preocupação, então a segunda função de Jamie Dixon é a melhor, mas não funciona completamente como está ...

Ele falha em colocar todas as letras em minúsculas e só coloca a primeira letra da string em maiúscula, não a primeira letra de cada palavra na string ... a opção abaixo corrige os dois 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);
    }

Embora, neste ponto, se esta ainda seja a opção mais rápida seja incerto, a Regexsolução fornecida por George Mauer pode ser mais rápida ... alguém que se preocupa o suficiente deve testá-la.

Serj Sagan
fonte
2
funciona, mas eu mudei "a.Contagem ()" para a. Comprimento
Cristão
2

Não sei se a solução abaixo é mais ou menos eficiente do que a resposta de jspcal, mas tenho quase certeza de que requer menos criação de objetos do que a de Jamie e 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
fonte
1
Se estamos preocupados com a criação de objetos, por que não fazer isso no local com uma indexação de loop for sobre s em vez de usar um StringBuilder?
jball
0

Além da primeira resposta, lembre-se de alterar o índice de início de seleção da string para o final da palavra ou você obterá a ordem inversa das letras na string.

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

Experimente esta técnica; Retorna o resultado desejado

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

E não se esqueça de usar System.Globalization.

Beyondo
fonte
0

Uma das soluções possíveis em que você pode estar interessado. Percorrer uma matriz de caracteres da direita para a esquerda e vice-versa em um loop.

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

A resposta de jspcal como uma extensão de string.

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
fonte