Сделать первую букву строки заглавной (с максимальной производительностью)

449

У меня есть DetailsViewс, TextBox и я хочу, чтобы входные данные были сохранены всегда с первой буквой КАПИТАЛА.

Пример:

"red" --> "Red"
"red house" --> " Red house"

Как я могу достичь этой максимальной производительности ?


ПРИМЕЧАНИЕ .
Исходя из ответов и комментариев к ответам, многие люди думают, что это вопрос об использовании всех слов в строке. Например , => Red House это не так , но если это то , что вы ищете , посмотрите на один из ответов , которые использует TextInfo«ы ToTitleCaseметод. (ПРИМЕЧАНИЕ. Эти ответы неверны для фактически заданного вопроса.)
См. Документ TextInfo.ToTitleCase для предостережений (не затрагивает все заглавные буквы - они считаются аббревиатурами; могут быть строчные буквы в середине слов, которые «не должны» быть понижено, например, "McDonald" => "Mcdonald"; не гарантировано обрабатывать все специфические для культуры тонкости правил капитализации.)


ПРИМЕЧАНИЕ :
Вопрос в том , неоднозначном , является ли письма после того , как первый должны быть вынуждены к нижнему регистру . Принятый ответ предполагает, что только первая буква должна быть изменена . Если вы хотите, чтобы все буквы в строке, кроме первой, были строчными, найдите ответ, содержащий ToLower, а не содержащий ToTitleCase .

Дилан-Myers
источник
7
@Bobby: Это не дубликат: ОП просит набрать первую букву строки с заглавной буквы, в вопросе по ссылке заглавная буква каждого слова.
GvS
1
@GvS: первый ответ очень подробный, а первый кодовый блок - именно то , что он ищет. Кроме того, между заглавными буквами каждого слова и только первым словом есть разница только в одну петлю.
Бобби
Вы когда-нибудь успешно решали это? Вам все еще нужна помощь с этим?
Jcolebrand
1
Но вы сказали, и я цитирую: «Сделайте первую букву КАЖДОГО СЛОВА в верхнем регистре». Поэтому, почему «красный дом» -> «Красный дом»? Почему буква "h" слова "дом" не является заглавной буквой?
Гильермо Гутьеррес
Добавлен ответ, так как большинство ответов не удастся, если у вас есть пробел в начале. чтобы не публиковать это в каждом ответе, я опубликую это здесь один раз.
Noctis

Ответы:

585

Обновлено до C # 8

public static class StringExtensions
{
    public static string FirstCharToUpper(this string input) =>
        input switch
        {
            null => throw new ArgumentNullException(nameof(input)),
            "" => throw new ArgumentException($"{nameof(input)} cannot be empty", nameof(input)),
            _ => input.First().ToString().ToUpper() + input.Substring(1)
        };
}

C # 7

public static class StringExtensions
{
    public static string FirstCharToUpper(this string input)
    {
        switch (input)
        {
            case null: throw new ArgumentNullException(nameof(input));
            case "": throw new ArgumentException($"{nameof(input)} cannot be empty", nameof(input));
            default: return input.First().ToString().ToUpper() + input.Substring(1);
        }
    }
}

Действительно старые ответы

public static string FirstCharToUpper(string input)
{
    if (String.IsNullOrEmpty(input))
        throw new ArgumentException("ARGH!");
    return input.First().ToString().ToUpper() + String.Join("", input.Skip(1));
}

РЕДАКТИРОВАТЬ : эта версия короче. Для более быстрого решения взгляните на ответ Equiso

public static string FirstCharToUpper(string input)
{
    if (String.IsNullOrEmpty(input))
        throw new ArgumentException("ARGH!");
    return input.First().ToString().ToUpper() + input.Substring(1);
}

РЕДАКТИРОВАТЬ 2 : Вероятно, самым быстрым решением является решение Даррена (есть даже эталон), хотя я бы изменил его string.IsNullOrEmpty(s)валидацию на исключение, так как исходное требование предполагает существование первой буквы, чтобы ее можно было вводить прописными буквами. Обратите внимание, что этот код работает для общей строки, а не только для допустимых значений из Textbox.

Карлос Муньос
источник
2
Потому что первый параметр String.Join- это разделитель, с которым соединяются строки, заданные вторым параметром.
Диалектик
27
Мне очень нравится ваш ответ, но var arr = input.ToCharArray(); arr[0] = Char.ToUpperInvariant(arr[0]); return new String(arr);, вероятно, вы получите некоторую скорость, поскольку вы создаете менее неизменные объекты (и особенно вы пропускаете String.Join). Это, конечно, зависит от длины строки.
Флиндеберг
3
Круто - Использование Linq очень ясно показывает, что делает этот код.
Даниэль Джеймс Брайерс
7
Хммм ... Технически, это должно вернуться, "Argh!"чтобы соответствовать правилу прописной буквы . ;)
jp2code
2
@ jp2code Так как использование несуществующей первой буквы в нулевой или пустой строке похоже на удар беременной дельфины, то ВСЕ КАПСЫ АРГ! это правильное написание. urbandictionary.com/define.php?term=ARGH&defid=67839
Карлос Муньос,
319
public string FirstLetterToUpper(string str)
{
    if (str == null)
        return null;

    if (str.Length > 1)
        return char.ToUpper(str[0]) + str.Substring(1);

    return str.ToUpper();
}

Старый ответ: это делает каждое первое письмо в верхнем регистре

public string ToTitleCase(string str)
{
    return CultureInfo.CurrentCulture.TextInfo.ToTitleCase(str.ToLower());
}
Диего Торрес
источник
Но это преобразует каждую первую букву слова в верхний регистр, а не только первый символ строки.
GvS
@GvS, это то, что вопрос просит тебя сделать.
thattolleyguy
17
Он спрашивает "красный дом" => "Красный дом". ToTitleCase выдаст вам «Красный дом».
GvS
1
полезно для меня. Отлично
Эхсан Саджад
1
Не уверен насчет этого, но char + string вызывает бокс. На всякий случай максимальная производительность является требованием.
Nawfal
164

Правильный путь заключается в использовании культуры:

System.Globalization.CultureInfo.CurrentCulture.TextInfo.ToTitleCase(word.ToLower())

Примечание: это будет использовать каждое слово в строке, например, «красный дом» -> «красный дом». Решение также будет использовать прописные буквы в словах, например «старый Макдональд» -> «старый Макдональд».

Пьер-Ив Гийем
источник
4
Это самый правильный способ сделать это, а не изобретать велосипед и попытаться написать собственную версию этого.
Алексей Шевелев
12
Проблема, с которой я столкнулся, заключается в том, что он будет стирать потенциально допустимые заглавные буквы, которые находятся в середине строки. например,
McNames
29
Это неправильный ответ по той причине, что «красный дом» становится «красным домом» (обратите внимание на «Н»)!
Спаарк
21
Через шесть лет после того, как вопрос был задан, пожалуйста, сделайте более тщательную работу по чтению существующих ответов и их комментариев . Если вы уверены, что у вас есть лучшее решение, покажите ситуации, в которых ваш ответ ведет себя так, как вы считаете превосходящими, и, в частности, как это отличается от существующих ответов. 1) Equiso уже освещал этот вариант во второй половине своего ответа. 2) Для многих ситуаций ToLowerэто ошибка, так как она уничтожает заглавные буквы в середине слова, например «Макдональдс». 3) Вопрос об изменении только первого слова строки , а не о TitleCase.
ToolmakerSteve
10
Это превращает ввод в «Заголовок» - то есть «красный конь» в «Красный конь», в то время как человек, спрашивающий, прямо заявил, что НЕ ДОЛЖЕН это делать (и возвращает «Красный конь»). Это не правильный путь.
Геккарык,
69

Я взял самый быстрый метод с http://www.dotnetperls.com/uppercase-first-letter и перешел на метод расширения:

    /// <summary>
    /// Returns the input string with the first character converted to uppercase, or mutates any nulls passed into string.Empty
    /// </summary>
    public static string FirstLetterToUpperCaseOrConvertNullToEmptyString(this string s)
    {
        if (string.IsNullOrEmpty(s))
            return string.Empty;

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

ПРИМЕЧАНИЕ. Причина, по которой используется ToCharArrayбыстрее, чем альтернатива char.ToUpper(s[0]) + s.Substring(1), заключается в том, что выделяется только одна строка, в то время как Substringподход выделяет строку для подстроки, а затем вторую строку для составления окончательного результата.


РЕДАКТИРОВАТЬ : Вот как выглядит этот подход, в сочетании с первоначальным тестом CarlosMuñoz принятый ответ :

    /// <summary>
    /// Returns the input string with the first character converted to uppercase
    /// </summary>
    public static string FirstLetterToUpperCase(this string s)
    {
        if (string.IsNullOrEmpty(s))
            throw new ArgumentException("There is no first letter");

        char[] a = s.ToCharArray();
        a[0] = char.ToUpper(a[0]);
        return new string(a);
    }
Даррен
источник
Спасибо, что нашли метрики производительности, чтобы показать решение с превосходной производительностью!
ToolmakerSteve
@ ToolmakerSteve, мне нравится это решение, так как оно действительно кажется быстрее других, но с этим есть небольшая проблема. Если вы передадите null, вы не должны получить пустую строку в качестве вывода. На самом деле, я бы сказал, что даже пропуск пустой строки должен вызывать исключение, поскольку OP запрашивает первую букву. Кроме того, вы можете прокомментировать ответы других людей, прежде чем редактировать их.
Карлос Муньос,
@ CarlosMuñoz - это было обсуждено в мета, чтобы "улучшить" ответы других людей. Консенсус заключался в том, что «если вы можете улучшить ответ, то сделайте это - никто не« владеет »ответом, даже оригинальный автор - цель состоит в том, чтобы получить наилучшие возможные ответы». Вы, конечно, можете редактировать или отменить редактирование. В этом случае обычная вежливость позволила бы исходной авторской версии получить окончательный результат, и я согласился бы прокомментировать. Обычно я также помещаю в комментарии изменения, которые я делаю; Я прошу прощения, если я не сделал.
ToolmakerSteve
@ CarlosMuñoz - в частности, в SO много, много ответов, которые активно не поддерживаются. Если изменение улучшит ответ, зачем оставлять его в комментарии? Если автор активно следит за своими ответами, они будут делать изменения по своему усмотрению. Если это не так, то ответ был улучшен, в интересах всех. Этот принцип особенно актуален для старых вопросов и ответов, таких как этот.
ToolmakerSteve
Кстати, я согласен с @ CarlosMuñoz по поводу теста в начале метода - его версия этого теста - лучший стиль программирования - return string.Emptyздесь будет скрываться «плохой» вызов метода.
ToolmakerSteve
46

Вы можете использовать «метод ToTitleCase»

string s = new CultureInfo("en-US").TextInfo.ToTitleCase("red house");
//result : Red House

этот метод расширения решает все проблемы заглавных букв.

прост в использовании

string str = "red house";
str.ToTitleCase();
//result : Red house

string str = "red house";
str.ToTitleCase(TitleCase.All);
//result : Red House

Метод расширения

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Globalization;

namespace Test
{
    public static class StringHelper
    {
        private static CultureInfo ci = new CultureInfo("en-US");
        //Convert all first latter
        public static string ToTitleCase(this string str)
        {
            str = str.ToLower();
            var strArray = str.Split(' ');
            if (strArray.Length > 1)
            {
                strArray[0] = ci.TextInfo.ToTitleCase(strArray[0]);
                return string.Join(" ", strArray);
            }
            return ci.TextInfo.ToTitleCase(str);
        }
        public static string ToTitleCase(this string str, TitleCase tcase)
        {
            str = str.ToLower();
            switch (tcase)
            {
                case TitleCase.First:
                    var strArray = str.Split(' ');
                    if (strArray.Length > 1)
                    {
                        strArray[0] = ci.TextInfo.ToTitleCase(strArray[0]);
                        return string.Join(" ", strArray);
                    }
                    break;
                case TitleCase.All:
                    return ci.TextInfo.ToTitleCase(str);
                default:
                    break;
            }
            return ci.TextInfo.ToTitleCase(str);
        }
    }

    public enum TitleCase
    {
        First,
        All
    }
}
Ибрагим Озболюк
источник
Проблема с вашим решением состоит в том, что «красный дом» будет преобразован в «Красный дом», а не в «Красный дом», как это было задано в вопросе.
Вадим
3
@Tacttin Это будет работать, но следующий код легче читать и лучше выполняет char.ToUpper (text [0]) + ((text.Length> 1)? Text.Substring (1) .ToLower (): string.Empty) ; Вы можете прочитать больше @ vkreynin.wordpress.com/2013/10/09/…
Вадим
1
Мне не нравится это решение, потому что оно объединяет две совершенно разные ситуации в один длинный метод. Я также не вижу концептуальной выгоды. И использование заглавных букв только в первом письме ... смешно. Если вы хотите использовать заглавные буквы в первой букве, очевидная реализация - просто заглавные буквы (ToUpper) первой буквы . Вместо этого у меня было бы два отдельных метода. FirstLetterToUpperв ответе Equiso (или в более новом ответе Guillernet) и ToTitleCaseздесь, но без второго параметра. Тогда не нужно enum TitleCase.
ToolmakerSteve
31

Для первой буквы с проверкой ошибок:

public string CapitalizeFirstLetter(string s)
{
    if (String.IsNullOrEmpty(s))
        return s;
    if (s.Length == 1)
        return s.ToUpper();
    return s.Remove(1).ToUpper() + s.Substring(1);
}

И вот так же, как удобное расширение

public static string CapitalizeFirstLetter(this string s)
    {
    if (String.IsNullOrEmpty(s)) return s;
    if (s.Length == 1) return s.ToUpper();
    return s.Remove(1).ToUpper() + s.Substring(1);
    }
Коби
источник
Чистый подход. Спасибо!
Филипп
11
public static string ToInvarianTitleCase(this string self)
{
    if (string.IsNullOrWhiteSpace(self))
    {
        return self;
    }

    return CultureInfo.InvariantCulture.TextInfo.ToTitleCase(self);
}
Big T
источник
6

Если производительность / использование памяти является проблемой, тогда создается только одна (1) строка StringBuilder и одна (1) новая строка того же размера, что и строка оригинала.

public static string ToUpperFirst(this string str) {
  if( !string.IsNullOrEmpty( str ) ) {
    StringBuilder sb = new StringBuilder(str);
    sb[0] = char.ToUpper(sb[0]);

    return sb.ToString();

  } else return str;
}
Даниэль Халан
источник
3
Это можно сделать с помощью простого, char[]а не наличия всей инфраструктуры StringBuilder. Вместо того new StringBuilder(str), чтобы использовать str.ToCharArray(), и вместо того sb.ToString(), чтобы использовать new string(charArray). StringBuilderэмулирует тип индексации, который массив символов предоставляет изначально, поэтому фактическая .ToUpperстрока может быть практически одинаковой. :-)
Джонатан Гилберт
Даррен (через год) показывает , как сделать это с помощью ToCharArray, как это было предложено @JonathanGilbert
ToolmakerSteve
6

Самый быстрый метод.

  private string Capitalize(string s){
        if (string.IsNullOrEmpty(s))
        {
            return string.Empty;
        }
        char[] a = s.ToCharArray();
        a[0] = char.ToUpper(a[0]);
        return new string(a);
}

Тесты показывают следующие результаты (строка с 10000000 символов в качестве входных данных): Результаты теста

Александр Иванов
источник
1
Я рекомендую вернуть sпараметр, когда ноль или пусто.
MatrixRonny
4

Попробуй это:

static public string UpperCaseFirstCharacter(this string text) {
    return Regex.Replace(text, "^[a-z]", m => m.Value.ToUpper());
}
JoelFan
источник
2
или, возможно, какой-то другой класс символов (т. е. алфавитно-цифровой \ w), чтобы функция поддерживала юникод
Дмитрий Леденцов
@ DmitryLedentsov- C # строковый класс построен на символах UTF-16. String Class "Представляет текст как последовательность кодовых единиц UTF-16."
ToolmakerSteve
4

Если вас волнует только то, что первая буква пишется с заглавной буквы, а остальная часть строки не имеет значения, вы можете просто выбрать первый символ, сделать его заглавным и объединить его с остальной частью строки без исходного первого символа.

String word ="red house";
word = word[0].ToString().ToUpper() + word.Substring(1, word.length -1);
//result: word = "Red house"

Нам нужно преобразовать первый символ ToString (), потому что мы читаем его как массив Char, а тип Char не имеет метода ToUpper ().

Виктор Гарсия
источник
3

Вот способ сделать это как метод расширения:

static public string UpperCaseFirstCharacter(this string text)
{
    if (!string.IsNullOrEmpty(text))
    {
        return string.Format(
            "{0}{1}",
            text.Substring(0, 1).ToUpper(),
            text.Substring(1));
    }

    return text;
}

Тогда можно назвать как:

//yields "This is Brian's test.":
"this is Brian's test.".UpperCaseFirstCharacter(); 

И вот некоторые модульные тесты для этого:

[Test]
public void UpperCaseFirstCharacter_ZeroLength_ReturnsOriginal()
{
    string orig = "";
    string result = orig.UpperCaseFirstCharacter();

    Assert.AreEqual(orig, result);
}

[Test]
public void UpperCaseFirstCharacter_SingleCharacter_ReturnsCapital()
{
    string orig = "c";
    string result = orig.UpperCaseFirstCharacter();

    Assert.AreEqual("C", result);
}

[Test]
public void UpperCaseFirstCharacter_StandardInput_CapitalizeOnlyFirstLetter()
{
    string orig = "this is Brian's test.";
    string result = orig.UpperCaseFirstCharacter();

    Assert.AreEqual("This is Brian's test.", result);
}
bingles
источник
1
string.Formatперебор; просто делай text.Substring(0, 1).ToUpper() + text.Substring(1).
ToolmakerSteve
3

Так как мне довелось работать над этим, и я искал какие-то идеи, к этому решению я пришел. Он использует LINQ и сможет использовать заглавные буквы первой строки, даже если первое вхождение не является буквой. Вот метод расширения, который я закончил.

public static string CaptalizeFirstLetter(this string data)
{
    var chars = data.ToCharArray();

    // Find the Index of the first letter
    var charac = data.First(char.IsLetter);
    var i = data.IndexOf(charac);

    // capitalize that letter
    chars[i] = char.ToUpper(chars[i]);

    return new string(chars);
}

Я уверен, что есть способ немного оптимизировать или очистить это.

CAOakley
источник
3

Я нашел кое-что здесь http://www.dotnetperls.com/uppercase-first-letter :

static string UppercaseFirst(string s)
{
// Check for empty string.
if (string.IsNullOrEmpty(s))
{
    return string.Empty;
}
// Return char and concat substring.
return char.ToUpper(s[0]) + s.Substring(1);
}

может это поможет !!

Мохаммед Замир
источник
Как это улучшение по сравнению с ответом Equiso 4 годами ранее?
ToolmakerSteve
3

Убедитесь, что строка не пуста, затем преобразуйте первый символ в верхний регистр, а остальные - в нижний регистр:

public static string FirstCharToUpper(string str)
{
    return str?.First().ToString().ToUpper() + str?.Substring(1).ToLower();
}
mbadeveloper
источник
Спасибо за небольшое решение вместо нескольких строк кода только за строковое слово!
Имран Фаруки
2

Это будет сделано, хотя и будет следить за тем, чтобы не было ошибочных заглавных букв в начале слова.

public string(string s)
{
System.Globalization.CultureInfo c = new System.Globalization.CultureInfo("en-us", false)
System.Globalization.TextInfo t = c.TextInfo;

return t.ToTitleCase(s);
}
Джефф Хорнби
источник
2
sНужна нулевая проверка перед вызовом ToTitleCase.
Тарас Аленин
@ CarlosMuñoz tlhIngan Hol не имеет буквенного регистра в своем сценарии. :-)
Джонатан Гилберт
2

Кажется, здесь много сложностей, когда все, что вам нужно, это:

    /// <summary>
    /// Returns the input string with the first character converted to uppercase if a letter
    /// </summary>
    /// <remarks>Null input returns null</remarks>
    public static string FirstLetterToUpperCase(this string s)
    {
        if (string.IsNullOrWhiteSpace(s))
            return s;

        return char.ToUpper(s[0]) + s.Substring(1);
    }

Интересные моменты:

  1. Это метод расширения.

  2. Если входное значение пустое или пустое, входное значение возвращается как есть.

  3. String.IsNullOrWhiteSpace был представлен в .NET Framework 4. Это не будет работать со старыми платформами.

Стивен Кеннеди
источник
1
Я не вижу, как это улучшение первоначального принятого ответа от четырехлетней давности. На самом деле, это противоречиво (безвредно, но спустя четыре года у меня есть высокие стандарты для нового ответа, добавляющего преимущество): единственное преимущество использования более нового IsNullOrWhiteSpace, чем IsNullOrEmpty, если вы собираетесь найти и изменить первое пустое пространство . Но вы не - вы всегда оперируете s[0]. Так что его бессмысленно [и семантически, и производительности] использовать IsNullOrWhiteSpace.
ToolmakerSteve
... почему IsNullOrWhiteSpaceменя беспокоит такое использование, потому что неосторожный читатель может подумать: «Он проверил наличие пробела, поэтому следующий код действительно находит и меняет букву, даже если ей предшествует пробел». Поскольку ваш код не сможет изменить «первую» букву, которой предшествует пробел, использование IsNullOrWhiteSpaceможет ввести в заблуждение только читателя.
ToolmakerSteve
... упс, я не имею в виду принятый ответ, я имею в виду ответ Эквизо за тот же период времени.
ToolmakerSteve
1
string emp="TENDULKAR";
string output;
output=emp.First().ToString().ToUpper() + String.Join("", emp.Skip(1)).ToLower();
Shailesh
источник
Почему ToLower () в хвосте? Там нет требования для других букв, кроме первого.
Карлос Муньос,
StringЭто может быть что угодно, Upperили. Так что Lowerэто общее решение для всей строки.
Шайлеш
Почему Joinвместо emp.First().ToString().ToUpper() + emp.Substring(1);? Наверное, нужно быть более оборонительным output = string.IsNullOrEmpty(emp) ? string.Empty : [...]. Кроме того, согласитесь с @ CarlosMuñoz - вам не нужен ToLower()вопрос ОП.
ruffin
@ ruffin -> использование Substring также является хорошим стилем написания кода, я согласен с вашим решением обрезать код, но в этом случае написание ToLower()- хорошая практика программирования. stringможет быть что угодно В Upperслучае, если Lowerслучай зависит от ввода пользователя, я даю общее решение.
Шайлеш
@Shailesh - Тем не менее, вопрос даже не просить , что только первая буква будет прописной. Он попросил изменить первую букву на заглавную. Без дальнейших разъяснений автора наиболее естественным является предположение, что оставшаяся часть строки не изменится. Учитывая, что вы отвечаете три года спустя , пожалуйста, предположите, что принятый ответ делает то, что просил запрашивающий. Дайте другой ответ, только если есть какая-то техническая причина сделать это по-другому.
ToolmakerSteve
1

Я хотел дать ответ «МАКСИМАЛЬНАЯ ЭФФЕКТИВНОСТЬ». На мой взгляд, ответ «МАКСИМАЛЬНАЯ ЭФФЕКТИВНОСТЬ» охватывает все сценарии и дает ответ на вопрос с учетом этих сценариев. Итак, вот мой ответ. По этим причинам:

  1. IsNullOrWhiteSpace учитывает строки, которые являются только пробелами или нулем / пустым.
  2. .Trim () удаляет пробелы в начале и в конце строки.
  3. .First () принимает первый символ перечисляемого (или строки).
  4. Мы должны проверить, является ли это письмо, которое может / должно быть в верхнем регистре.
  5. Затем мы добавляем остальную часть строки, только если длина указывает, что мы должны.
  6. В соответствии с передовой практикой .Net мы должны предоставить культуру в System.Globalization.CultureInfo.
  7. Предоставление их в качестве необязательных параметров делает этот метод полностью пригодным для повторного использования без необходимости каждый раз вводить выбранную культуру.

    public static string capString(string instring, string culture = "en-US", bool useSystem = false)
    {
        string outstring;
        if (String.IsNullOrWhiteSpace(instring))
        {
            return "";
        }
        instring = instring.Trim();
        char thisletter = instring.First();
        if (!char.IsLetter(thisletter))
        {
            return instring;   
        }
        outstring = thisletter.ToString().ToUpper(new CultureInfo(culture, useSystem));
        if (instring.Length > 1)
        {
            outstring += instring.Substring(1);
        }
        return outstring;
    }
Патрик Нотт
источник
2
Хотя это охватывает большинство случаев, не будет ли это довольно медленным, учитывая количество строк, создаваемых с каждой операцией? Здесь происходит тонна выделения строк. Желательно, чтобы он был выделен один раз и только один раз.
Дуглас Гаскелл
1

Недавно у меня было похожее требование, и я вспомнил, что функция LINQ Select () предоставляет индекс:

string input;
string output;

input = "red house";
output = String.Concat(input.Select((currentChar, index) => index == 0 ? Char.ToUpper(currentChar) : currentChar));
//output = "Red house"

Поскольку мне это нужно очень часто, я сделал метод расширения для строкового типа:

public static class StringExtensions
{
    public static string FirstLetterToUpper(this string input)
    {
        if (string.IsNullOrEmpty(input))
            return string.Empty;
        return String.Concat(input.Select((currentChar, index) => index == 0 ? Char.ToUpper(currentChar) : currentChar));
    }
}

Обратите внимание, что только первая буква преобразуется в верхний регистр - все остальные символы не затрагиваются. Если вам нужны другие символы в нижнем регистре, вы также можете вызвать Char.ToLower (currentChar) для index> 0 или вызвать ToLower () для всей строки в первую очередь.

Что касается производительности, я сравнил код с решением от Darren. На моей машине код Даррена примерно в 2 раза быстрее, что неудивительно, поскольку он напрямую редактирует только первую букву в массиве символов. Поэтому я предлагаю вам взять код Даррена, если вам нужно самое быстрое из доступных решений. Если вы хотите интегрировать и другие манипуляции со строками, может быть удобно, чтобы выразительная сила лямбда-функции касалась символов входной строки - вы можете легко расширить эту функцию - поэтому я оставлю это решение здесь.

Гримм
источник
Мне было интересно, как бы я решил эту проблему, разработал свое собственное решение, а затем вернулся, чтобы опубликовать его, и обнаружил, что вы придумали точно такое же решение, которое я уже имел. +1 тебе!
BlueFuzzyThing
Большое спасибо.
Гримм
1

Я думаю, что метод ниже является лучшим решением

    class Program
{
    static string UppercaseWords(string value)
    {
        char[] array = value.ToCharArray();
        // Handle the first letter in the string.
        if (array.Length >= 1)
        {
            if (char.IsLower(array[0]))
            {
                array[0] = char.ToUpper(array[0]);
            }
        }
        // Scan through the letters, checking for spaces.
        // ... Uppercase the lowercase letters following spaces.
        for (int i = 1; i < array.Length; i++)
        {
            if (array[i - 1] == ' ')
            {
                if (char.IsLower(array[i]))
                {
                    array[i] = char.ToUpper(array[i]);
                }
            }
        }
        return new string(array);
    }

    static void Main()
    {
        // Uppercase words in these strings.
        const string value1 = "something in the way";
        const string value2 = "dot net PERLS";
        const string value3 = "String_two;three";
        const string value4 = " sam";
        // ... Compute the uppercase strings.
        Console.WriteLine(UppercaseWords(value1));
        Console.WriteLine(UppercaseWords(value2));
        Console.WriteLine(UppercaseWords(value3));
        Console.WriteLine(UppercaseWords(value4));
    }
}

Output

Something In The Way
Dot Net PERLS
String_two;three
 Sam

ссылка

D.JCode
источник
1

Поскольку этот вопрос касается максимизации производительности, я принял версию Даррена для использования Spans, которая уменьшает мусор и повышает скорость примерно на 10%.

        /// <summary>
        /// Returns the input string with the first character converted to uppercase
        /// </summary>
        public static string ToUpperFirst(this string s)
        {
            if (string.IsNullOrEmpty(s))
                throw new ArgumentException("There is no first letter");

            Span<char> a = stackalloc char[s.Length];
            s.AsSpan(1).CopyTo(a.Slice(1));
            a[0] = char.ToUpper(s[0]);
            return new string(a);
        }

Представление

|  Method |      Data |      Mean |     Error |    StdDev |
|-------- |---------- |----------:|----------:|----------:|
|  Carlos |       red | 107.29 ns | 2.2401 ns | 3.9234 ns |
|  Darren |       red |  30.93 ns | 0.9228 ns | 0.8632 ns |
| Marcell |       red |  26.99 ns | 0.3902 ns | 0.3459 ns |
|  Carlos | red house | 106.78 ns | 1.9713 ns | 1.8439 ns |
|  Darren | red house |  32.49 ns | 0.4253 ns | 0.3978 ns |
| Marcell | red house |  27.37 ns | 0.3888 ns | 0.3637 ns |

Полный тестовый код

using System;
using System.Linq;

using BenchmarkDotNet.Attributes;

namespace CorePerformanceTest
{
    public class StringUpperTest
    {
        [Params("red", "red house")]
        public string Data;

        [Benchmark]
        public string Carlos() => Data.Carlos();

        [Benchmark]
        public string Darren() => Data.Darren();

        [Benchmark]
        public string Marcell() => Data.Marcell();
    }

    internal static class StringExtensions
    {
        public static string Carlos(this string input) =>
            input switch
            {
                null => throw new ArgumentNullException(nameof(input)),
                "" => throw new ArgumentException($"{nameof(input)} cannot be empty", nameof(input)),
                _ => input.First().ToString().ToUpper() + input.Substring(1)
            };

        public static string Darren(this string s)
        {
            if (string.IsNullOrEmpty(s))
                throw new ArgumentException("There is no first letter");

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

        public static string Marcell(this string s)
        {
            if (string.IsNullOrEmpty(s))
                throw new ArgumentException("There is no first letter");

            Span<char> a = stackalloc char[s.Length];
            s.AsSpan(1).CopyTo(a.Slice(1));
            a[0] = char.ToUpper(s[0]);
            return new string(a);
        }
    }

}

Редактировать: было типо, вместо s [0], было [0] - это приводит к тому, что купирование совпадает с пустым значением выделенного диапазона a.

Марсель Тот
источник
0

Это заглавная буква первая и каждая буква после пробела и строчные буквы любой другой буквы.

public string CapitalizeFirstLetterAfterSpace(string input)
{
    System.Text.StringBuilder sb = new System.Text.StringBuilder(input);
    bool capitalizeNextLetter = true;
    for(int pos = 0; pos < sb.Length; pos++)
    {
        if(capitalizeNextLetter)
        {
            sb[pos]=System.Char.ToUpper(sb[pos]);
            capitalizeNextLetter = false;
        }
        else
        {
            sb[pos]=System.Char.ToLower(sb[pos]);
        }

        if(sb[pos]=' ')
        {
            capitalizeNextLetter=true;
        }
    }
}
thattolleyguy
источник
1
Или, если вы не хотите писать стены кода - CultureInfo.CurrentCulture.TextInfo.ToTitleCase (theString); делает то же самое.
Chev
Да ... я не знал об этом :) И из-за моего огромного количества кода, ответы всех остальных выскакивали, пока я все еще печатал.
thattolleyguy
UPVOTED: 1) Небольшое различие между этим ответом и ToTitleCase состоит в том, что этот ответ заставляет слова, которые являются заглавными буквами, стать TitleCase, тогда как ToTitleCase оставляет такие слова в покое (предполагается, что они могут быть аббревиатурами). Это может или не может быть то, что желательно. Преимущество такого примера кода состоит в том, что он может быть изменен по желанию. 2) это не будет правильно обрабатывать пробелы, кроме ''. следует заменить пустой тест на пробел.
ToolmakerSteve
0

Используйте следующий код:

string  strtest ="PRASHANT";
strtest.First().ToString().ToUpper() + strtest.Remove(0, 1).ToLower();
Прашант Банавали
источник
Моему представителю не стоит даже баллотировать этот ответ, добавленный спустя годы, что, очевидно, эквивалентно уже существующим ответам. Если вы собираетесь добавить новый ответ на вопрос со многими ответами, пожалуйста, объясните, что, по вашему мнению, лучше вашего ответа, или при каких обстоятельствах ваш ответ будет более полезным, чем другие ответы. Быть конкретным.
ToolmakerSteve
0

Похоже, что ни одно из приведенных здесь решений не будет иметь дело с пробелом перед строкой.

Просто добавив это как мысль:

public static string SetFirstCharUpper2(string aValue, bool aIgonreLeadingSpaces = true)
{
    if (string.IsNullOrWhiteSpace(aValue))
        return aValue;

    string trimmed = aIgonreLeadingSpaces 
           ? aValue.TrimStart() 
           : aValue;

    return char.ToUpper(trimmed[0]) + trimmed.Substring(1);
}   

Он должен обрабатывать this won't work on other answers(это предложение имеет пробел в начале), и если вам не нравится обрезка пробела, просто передайтеfalse качестве второго параметра (или измените значение по умолчанию на false, и передайте, trueесли вы хотите иметь дело с пробелом)

Ноктис
источник
0

Самый простой способ заглавной буквы:

1- Использование Sytem.Globalization;

  // Creates a TextInfo based on the "en-US" culture.
  TextInfo myTI = new CultureInfo("en-US",false).

  myTI.ToTitleCase(textboxname.Text)

`

Саад Халид
источник
1
Этот ответ по существу идентичен ответам, данным годами ранее. Это ничего не добавляет к обсуждению.
ToolmakerSteve
Это также неправильно, так же как и комментарий в другом, это превращает каждую первую букву во всех словах прописной буквы, а не в Красный дом вместо Красного дома.
DeadlyChambers
0

следующая функция верна для всех способов:

static string UppercaseWords(string value)
{
    char[] array = value.ToCharArray();
    // Handle the first letter in the string.
    if (array.Length >= 1)
    {
        if (char.IsLower(array[0]))
        {
            array[0] = char.ToUpper(array[0]);
        }
    }
    // Scan through the letters, checking for spaces.
    // ... Uppercase the lowercase letters following spaces.
    for (int i = 1; i < array.Length; i++)
    {
        if (array[i - 1] == ' ')
        {
            if (char.IsLower(array[i]))
            {
                array[i] = char.ToUpper(array[i]);
            }
        }
    }
    return new string(array);
}

Я нашел это здесь


источник
Почему? Зачем добавлять еще один ответ, когда уже есть так много ответов, которые кажутся похожими? Что не так со всеми существующими ответами, которые побудили вас добавить еще один?
ToolmakerSteve
Потому что этот ответ правильно для всех способов. Не принимайте это близко к сердцу.
Я прошу прощения; Я был излишне резок. Я придерживаюсь фактов: 1) По сути, это то же самое, что и тот ответ Толлигуя семь лет назад. 2) Это имеет тот же недостаток, что и ответ: не обрабатывает пробелы, кроме пустых символов. 3) Это отвечает на несколько иной вопрос, чем задавал ОП. Используйте ответ, подобный этому, если вы хотите, чтобы все слова начинались с заглавной буквы. 4) Как правило, более простой способ сделать это - использовать TitleInfo.ToTitleCase. (С другой стороны, преимущество пример кода можно настроить по желанию.)
ToolmakerSteve
Поправляю себя: Это отличается от подхода этого единственного человека: он оставляет нетронутыми буквы, которые не являются первой буквой слова. Вместо этого, он является дубликатом из ответа zamoldar в . Благоприятно, спасибо Дариану за то, что он дал ссылку на источник - кажется, что замольдар плагиат, не отдавая должного. Из-за предоставления ссылки на источник и, тем самым, улучшения обсуждения , я поддерживаю этот ответ, несмотря на мою критику.
ToolmakerSteve
1
Дариан, два улучшения, которые можно сделать: 1) использовать char.IsWhiteSpace( array[ i -1 ] )вместо того .. == ' ', чтобы обрабатывать все пробелы. 2) удалить два места, которые делают if (char.isLower(..))- они не служат цели. ToUpperпросто ничего не делает, если символ не в нижнем регистре.
ToolmakerSteve
0

Расширяя вопрос Карлоса выше, если вы хотите использовать несколько предложений с большой буквы, вы можете использовать этот код:

    /// <summary>
    /// Capitalize first letter of every sentence. 
    /// </summary>
    /// <param name="inputSting"></param>
    /// <returns></returns>
    public string CapitalizeSentences (string inputSting)
    {
        string result = string.Empty;
        if (!string.IsNullOrEmpty(inputSting))
        {
            string[] sentences = inputSting.Split('.');

            foreach (string sentence in sentences)
            {
                result += string.Format ("{0}{1}.", sentence.First().ToString().ToUpper(), sentence.Substring(1)); 
            }
        }

        return result; 
    }
Замир
источник
0

Возможное решение для решения вашей проблемы.

   public static string FirstToUpper(this string lowerWord)
   {
       if (string.IsNullOrWhiteSpace(lowerWord) || string.IsNullOrEmpty(lowerWord))
            return lowerWord;
       return new StringBuilder(lowerWord.Substring(0, 1).ToUpper())
                 .Append(lowerWord.Substring(1))
                 .ToString();
   }
Сая Имад
источник