Преобразуйте всю первую букву в верхний регистр, оставайтесь ниже для каждого слова

110

У меня есть строка текста (в основном около 5-6 слов), которую мне нужно преобразовать.

На данный момент текст выглядит так:

THIS IS MY TEXT RIGHT NOW

Я хочу преобразовать его в:

This Is My Text Right Now

Я могу перебрать мою коллекцию строк, но не знаю, как выполнить эту модификацию текста.

mrblah
источник

Ответы:

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

s = System.Threading.Thread.CurrentThread.CurrentCulture.TextInfo.ToTitleCase(s.ToLower());
jspcal
источник
31
Хаха реально? Вот где это? Я люблю .NET, но некоторые разработчики API - настоящие придурки.
Джордж Мауэр
7
Обратите внимание, что хотя этот метод будет делать то, о чем спрашивает спрашивающий, это наивный алгоритм, который просто использует каждое слово с заглавной буквы, независимо от того, что это за слово. Это не совсем «заглавный регистр», поскольку правила для заглавных букв различаются на разных языках. Это даже не правильно для английского. Например, заголовок «about a boy» должен быть «About a Boy» на английском языке, но этот метод даст «About A Boy». Если вам нужен настоящий регистр заголовка, вам придется написать свой собственный метод.
Райан Ланди
18
Я бы не назвал их придурками. Дело в том, что ToTitleCase зависит от языка и региональных параметров, поэтому он должен находиться в пространстве имен System.Globalization. Прохождение CurrentThread выполняется только для получения текущей культуры потока (имейте в виду, что это может привести к другому поведению, если у пользователя другой языковой стандарт!). Вы также можете сделать "CultureInfo.InvariantCulture.TextInfo.ToTitleCase ()", что может быть лучше, поскольку InvariantCulture ведет себя одинаково для всех культур. Ради интереса Джордж: Где бы вы поместили строковую функцию, зависящую от культуры?
Майкл Стум
3
Также обратите внимание на комментарии ко ВСЕМ ЗАПИСНЫМ строчкам
Майкл
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

РЕДАКТИРОВАТЬ

На самом деле эти решения являются не то же самое : 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);
    }

Второй способ (который немного быстрее) - разбить строку на массив символов, а затем заново построить строку:

public string UppercaseFirst(string s)
    {
        char[] a = s.ToCharArray();
        a[0] = char.ToUpper(a[0]);
        return new string(a);
    }
Джейми Диксон
источник
1
Это решение не совсем точно отвечает на вопрос. Заголовок вопроса: «Преобразовать все первые буквы в верхний регистр, остальные нижние для каждого слова». Однако это решение использует только первую букву всей строки. Следовательно, это решение преобразует «hello world» в «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
Джей
1
Тег ASP.NETпоказывает, что OP делает это через WEB. Конечно, это не ответ на вопрос, потому что OP требовал решения, 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
Christian
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();
ephemient
источник
1
Если нас интересует создание объекта, почему бы не сделать это на месте с помощью индексации цикла for по s вместо использования StringBuilder?
jball
0

В дополнение к первому ответу не забудьте изменить указатель начала выделения строки на конец слова, иначе вы получите обратный порядок букв в строке.

s.SelectionStart=s.Length;
Зия Хан
источник
0

Попробуйте эту технику; Возвращает желаемый результат

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

И не забывайте использовать System.Globalization.

Beyondo
источник
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());
    }
}
Джоэл Виклунд
источник