Перетворіть усі перші букви в великі регістри, решту - нижню для кожного слова


110

У мене є рядок тексту (здебільшого 5-6 слів), який мені потрібно перетворити.

Наразі текст виглядає так:

THIS IS MY TEXT RIGHT NOW

Я хочу перетворити його на:

This Is My Text Right Now

Я можу переглядати колекцію рядків, але не знаю, як рухатись до виконання цієї модифікації тексту.

Відповіді:


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

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

31
Ха-ха, справді? Ось де це? Я люблю .NET, але деякі дизайнери API - це справжні ривки.
Джордж Мауер

7
Зауважте, що, хоча цей метод буде робити те, що запитував, запитуючий, це наївний алгоритм, який просто з великої літери використовує кожне слово, без огляду на те, яке це слово. Це насправді не "заголовок справи", оскільки правила для заголовка відрізняються різними мовами. Для англійської це навіть не правильно. Наприклад, назва "про хлопчика" повинна бути "Про хлопчика" англійською мовою, але цей метод дав би "Про хлопчика". Якщо ви хочете справжнього випадку з заголовком, вам доведеться написати власний метод.
Райан Лунді

18
Я б не називав їх ривками. Річ із "ToTitleCase" полягає в тому, що це залежить від культури, отже, воно повинно бути в просторі імен System.Globalization. Проходження CurrentThread робиться лише для того, щоб отримати поточну культуру нитки (пам’ятайте, що це може спричинити різну поведінку, якщо користувач має інший Локальний!). Ви також можете зробити "CultureInfo.InvariantCulture.TextInfo.ToTitleCase ()", що може бути краще, оскільки InvariantCulture поводиться однаково у всіх культурах. Нецікаво Джордж: Куди б ти поставив функцію String-специфічної струни?
Майкл Стум

3
Також зверніть увагу на коментарі до ВСІХ РОЗВИТКІВ струн: msdn.microsoft.com/en-us/library/…
Michael

2
метод toLower () повинен бути ToLower (), перша буква методу починається з верхньої літери
Alex

84

Я , ймовірно , вважають за краще посилатися на ToTitleCase з CultureInfo ( System.Globalization ) , ніж Thread.currentThread ( System.Threading )

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

але це повинно бути таким же, як jspcal рішення

EDIT

На насправді ці рішення є не те ж саме : 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

Список літератури:


16

Існує кілька способів перетворення першого символу рядка у верхній регістр.

Перший спосіб - це створити метод, який просто обмежує першу таблицю і додає решту рядка за допомогою підрядка:

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

Другий спосіб (який трохи швидше) - розділити рядок на масив char, а потім відновити рядок:

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

1
Це рішення не відповідає належним чином на питання. Назва запитання - "Перетворити всю першу букву у верхній регістр, решту нижню за кожне слово". Однак це рішення лише з великої літери використовує першу букву всього рядка. Тому це рішення перетворило б "привіт світ" на "Hello world", а не "Hello World".
brsfan

9

Неперевірений, але щось подібне повинно працювати:

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

По суті, він говорить "заздалегідь підберіть форму відповідності для всіх випадків буквено-цифрового символу, який слід за іншим буквено-цифровим символом, а потім замініть його на малу версію себе"


Цей також змушує всі великі слова починатись з великих літер і продовжуватись з малих літер. Саме те, що я шукав.
М. Азіоксул

9

Якщо ви використовуєте веб-сторінку, ви також можете використовувати CSS:

style="text-transform:capitalize;"


2
Чому CSS? Коли питання задається регексом c # asp.net
Jay,

1
Тег ASP.NETпоказує, що ОП робить це в WEB. Звичайно, це не відповідь на питання, оскільки ОП вимагало рішення, C#але це вирішує проблему і може бути альтернативним рішенням. +1
Мухаммед Сакіб

6

Під час створення великих таблиць швидкість викликає занепокоєння, тому найкраща друга функція Джеймі Діксона, але вона не працює повністю, як це ...

Він не може перенести всі літери в малі регістри, і він використовує великі літери першої літери рядка, а не першої літери кожного слова в рядку ... нижче наведений варіант виправляє обидва питання:

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

Хоча на даний момент, чи це все-таки найшвидший варіант, невірно, Regexрішення Джорджа Мауера може бути швидшим ... той, хто достатньо піклується, повинен перевірити це.


2
це працює, але я змінив цей "a.Count ()" на a.Length
Крістіан

2

Я не знаю, чи рішення нижче є більш-менш ефективним, ніж відповідь jspcal, але я впевнений, що для цього потрібно менше об'єктів, ніж Джеймі та Джорджа.

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
Якщо ми переймаємось створенням об'єктів, чому б не зробити це замість індексації циклу через s замість використання StringBuilder?
jball

0

На додаток до першої відповіді, не забудьте змінити індекс початку вибору рядка до кінця слова, інакше ви отримаєте зворотній порядок літер у рядку.

s.SelectionStart=s.Length;

0

Спробуйте цю техніку; Це повертає бажаний результат

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

І не забудьте скористатися System.Globalization.


0

Одне з можливих рішень, яке може вас зацікавити. Проходження масиву символів справа наліво та навпаки в одну петлю.

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

Відповідь jspcal як розширення рядка

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());
    }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.