Converti tutta la prima lettera in maiuscolo, resta in minuscolo per ogni parola


110

Ho una stringa di testo (circa 5-6 parole per lo più) che devo convertire.

Attualmente il testo ha questo aspetto:

THIS IS MY TEXT RIGHT NOW

Voglio convertirlo in:

This Is My Text Right Now

Posso scorrere la mia raccolta di stringhe, ma non sono sicuro di come eseguire questa modifica del testo.

Risposte:


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

s = System.Threading.Thread.CurrentThread.CurrentCulture.TextInfo.ToTitleCase(s.ToLower());

31
Ahah davvero? Ecco dov'è? Amo .NET ma alcuni dei progettisti di API sono dei veri e propri cretini.
George Mauer,

7
Nota che mentre questo metodo farà ciò che l'interrogante ha chiesto, è un algoritmo ingenuo che capitalizza ogni parola, indipendentemente dal tipo di parola che è. Non è realmente "maiuscole / minuscole" poiché le regole per le maiuscole / minuscole differiscono nelle diverse lingue. Non è nemmeno corretto per l'inglese. Ad esempio, il titolo "about a boy" dovrebbe essere "About a Boy" in inglese, ma questo metodo darebbe "About A Boy". Se vuoi un vero caso del titolo, dovrai scrivere il tuo metodo.
Ryan Lundy

18
Non li chiamerei cretini. Il problema con "ToTitleCase" è che dipende dalle impostazioni cultura, quindi deve essere nello spazio dei nomi System.Globalization. L'esecuzione di CurrentThread viene eseguita solo per ottenere la cultura corrente del thread (tenere presente che ciò potrebbe causare un comportamento diverso se l'utente ha una lingua diversa!). Potresti anche fare "CultureInfo.InvariantCulture.TextInfo.ToTitleCase ()", che potrebbe essere migliore in quanto InvariantCulture si comporta allo stesso modo su tutte le culture. Per interesse George: Dove metteresti una funzione di stringa specifica per la cultura?
Michael Stum

3
Nota anche i commenti su TUTTE le stringhe MAIUSCOLE: msdn.microsoft.com/en-us/library/…
Michael Stum

2
il metodo toLower () dovrebbe essere ToLower (), la prima lettera del metodo inizia con maiuscolo
Alex

84

Probabilmente preferisco richiamare ToTitleCase da CultureInfo ( System.Globalization ) piuttosto che Thread.CurrentThread ( System.Threading )

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

ma dovrebbe essere lo stesso della soluzione jspcal

MODIFICARE

In realtà quelle soluzioni non sono le stesse : 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

Riferimenti:


16

Ci sono un paio di modi per convertire il primo carattere di una stringa in maiuscolo.

Il primo modo è creare un metodo che tappi semplicemente il primo carattere e aggiunga il resto della stringa usando una sottostringa:

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

Il secondo modo (che è leggermente più veloce) è dividere la stringa in un array di caratteri e quindi ricostruire la stringa:

public string UppercaseFirst(string s)
    {
        char[] a = s.ToCharArray();
        a[0] = char.ToUpper(a[0]);
        return new string(a);
    }

1
Questa soluzione non risponde esattamente alla domanda in modo adeguato. Il titolo della domanda è "Converti tutta la prima lettera in maiuscolo, resta in basso per ogni parola". Tuttavia, questa soluzione rende maiuscola solo la prima lettera dell'intera stringa. Pertanto, questa soluzione convertirà "ciao mondo" in "ciao mondo", anziché "ciao mondo".
brsfan

9

Non testato ma qualcosa di simile dovrebbe funzionare:

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()));

Essenzialmente dice "preforma una corrispondenza regex su tutte le occorrenze di un carattere alfanumerico che segue un altro carattere alfanumerico e poi sostituiscilo con una versione minuscola di se stesso"


Questo fa anche in modo che tutte le parole maiuscole inizino con le maiuscole e continuino con le minuscole. Esattamente quello che stavo cercando.
M. Azyoksul

9

Se stai usando su una pagina web, puoi anche usare CSS:

style="text-transform:capitalize;"


2
Perché CSS? Quando la domanda chiede di c # asp.net regex
Jay

1
Il tag ASP.NETmostra che l'OP lo sta facendo sul WEB. Ovviamente questa non è la risposta alla domanda perché OP ha richiesto la soluzione in C#ma risolve il problema e può essere una soluzione alternativa. +1
Muhammad Saqib

6

Quando si costruiscono tavoli grandi la velocità è un problema, quindi la seconda funzione di Jamie Dixon è la migliore, ma non funziona completamente come è ...

Non riesce a portare tutte le lettere in minuscolo e rende maiuscola solo la prima lettera della stringa, non la prima lettera di ogni parola nella stringa ... l'opzione seguente risolve entrambi i problemi:

    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);
    }

Anche se a questo punto non è Regexchiaro se questa sia ancora l'opzione più veloce, la soluzione fornita da George Mauer potrebbe essere più veloce ... qualcuno che se ne frega abbastanza dovrebbe provarla.


2
funziona, ma ho cambiato questo "a.Count ()" in a.Length
Christian

2

Non so se la soluzione seguente sia più o meno efficiente della risposta di jspcal, ma sono abbastanza sicuro che richieda meno creazione di oggetti rispetto a quella di 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();

1
Se siamo interessati alla creazione di oggetti, perché non farlo sul posto con un'indicizzazione del ciclo for su s invece di utilizzare uno StringBuilder?
jball

0

Oltre alla prima risposta, ricordati di cambiare l'indice iniziale di selezione della stringa alla fine della parola o otterrai l'ordine inverso delle lettere nella stringa.

s.SelectionStart=s.Length;

0

Prova questa tecnica; Restituisce il risultato desiderato

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

E non dimenticare di usare System.Globalization.


0

Una delle possibili soluzioni a cui potresti essere interessato. Attraversare un array di caratteri da destra a sinistra e viceversa in un ciclo.

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);
    }

0

La risposta di jspcal come estensione di stringa.

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());
    }
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.