BestPractice - Перетворення першого символу рядка в малі регістри


136

Я хотів би мати метод, який перетворює перший символ рядка в малі регістри.

Мої підходи:

1.

public static string ReplaceFirstCharacterToLowerVariant(string name)
{
    return String.Format("{0}{1}", name.First().ToString().ToLowerInvariant(), name.Substring(1));
}

2.

public static IEnumerable<char> FirstLetterToLowerCase(string value)
{
    var firstChar = (byte)value.First();
    return string.Format("{0}{1}", (char)(firstChar + 32), value.Substring(1));
}

Яким був би ваш підхід?

Відповіді:


239

Я б використовував просту конкатенацію:

Char.ToLowerInvariant(name[0]) + name.Substring(1)

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

Підхід з "+ 32" некрасивий / недоцільний, оскільки він вимагає значень компенсацій значення символів ASCII. Він також генеруватиме неправильний вихід із даними Unicode та символами ASCII.


4
я б це зробив:char.ToLower(name[0]).ToString() + name.Substring(1)
Андрій

7
@Rookian: +оператор повільний, коли ви об'єднуєте багато рядків. У такому випадку a працював StringBuilderби набагато краще. Однак +це набагато швидше, ніж string.Format. Використовуйте останнє, коли вам потрібно щось відформатувати (наприклад, для відображення цілих чисел, парних чи дат).
Дірк Волмар

6
@ 0x03: це лише повільно, якщо ви повторно поєднуєте безліч рядків. Якщо ви об'єднаєте їх за одну операцію, +оператор зовсім не повільний, тому що компілятор перетворює це на String.Concat(проте String.Joinшвидше, ніж String.Concatз якихось дурних причин).
Торарін

2
Більш швидкий метод такий: загальнодоступна статична рядок ToFirstLetterLower (текст рядка) {var charArray = text.ToCharArray (); charArray [0] = char.ToLower (charArray [0]); повернути новий рядок (charArray); }
Маттео Мільйоре

2
Я використовував розширення на public static string ToLowerFirst(this string source) { if (string.IsNullOrWhiteSpace(source)) return source; var charArray = source.ToCharArray(); charArray[0] = char.ToLower(charArray[0]); return new string(charArray); } основі коментаря @ MatteoMigliore.
KregHEk

64

Залежно від ситуації може бути бажаним трохи захисного програмування:

public static string FirstCharacterToLower(string str)
{
    if (String.IsNullOrEmpty(str) || Char.IsLower(str, 0))
        return str;

    return Char.ToLowerInvariant(str[0]) + str.Substring(1);
}

Оператор ifтакож не дозволяє будувати новий рядок, якщо він все одно не буде змінений. Можливо, ви хочете, щоб метод не працював на нульовому введенні, і кинути ArgumentNullException.

Як згадували люди, використання String.Formatдля цього є надмірним.


Виправте мене, якщо я помиляюся, але str.Substring (1) поверне символ у позиції 1, оскільки кількість цього методу не вказана. тож у вас буде char [0] в нижньому регістрі + char у позиції 1 Тому я вважав за краще видалити один char, починаючи з першого char у рядку. Результат - рядок без першої літери. Тоді я додаю цей рядок до першого знаку, який перетворюється на малі
регістри

3
@ B-Rain: вважати себе виправив: msdn.microsoft.com/en-us/library/hxthx5h6%28VS.90%29.aspx
Торарінн

7

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

Я думаю, що це було б найкраще як метод розширення, тоді ви можете викликати це за допомогою yourString.FirstCharacterToLower ();

public static class StringExtensions
{
    public static string FirstCharacterToLower(this string str)
    {
        if (String.IsNullOrEmpty(str) || Char.IsLower(str, 0))
        {
            return str;
        }

        return Char.ToLowerInvariant(str[0]) + str.Substring(1);
    }
}

3

Моя є

if (!string.IsNullOrEmpty (val) && val.Length > 0)
{
    return val[0].ToString().ToLowerInvariant() + val.Remove (0,1);   
}

3
Мені цікаво, чому val.Remove? Здається мені трохи контр-інтуїтивно зрозумілим.
Торарін

@Thorarin очевидно тому, що ви хочете видалити перший char (тому що ви додаєте нижню версію передньої версії)
Riki

2

Мені подобається прийнята відповідь, але крім перевірки string.IsNullOrEmptyя також перевіряю, чи не Char.IsLower(name[1])маєте ви справу з абревіатурою. Наприклад, ви б не хотіли, щоб "СНІД" став "СНІДом".


8
ІМО це відповідальність викликає
onof

1

Найшвидше рішення, яке я знаю, не зловживаючи c #:

public static string LowerCaseFirstLetter(string value)
{
    if (value?.Length > 0)
    {
        var letters = value.ToCharArray();
        letters[0] = char.ToLowerInvariant(letters[0]);
        return new string(letters);
    }
    return value;
}

0

Об’єднав декілька і зробив це прийнятним продовженням. Додано коротке замикання на пробіли та не букви.

public static string FirstLower(this string input) => 
    (!string.IsNullOrWhiteSpace(input) && input.Length > 0 
        && char.IsLetter(input[0]) && !char.IsLower(input[0]))
    ? input[0].ToString().ToLowerInvariant() + input.Remove(0, 1) : input;

0

Це невеликий метод розширення з використанням останнього синтаксису та правильних перевірок

public static class StringExtensions
{
    public static string FirstCharToLower(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().ToLower() + input.Substring(1);
        }
    }
}

1
Не впевнений, чи найкращим рішенням буде кидання виключення. Якщо рядок є нульовим або порожнім, просто поверніть нульовий або порожній рядок.
Р. де Вен

Якщо рядок є нульовим або порожнім, операція не має сенсу, оскільки немає першого знака, який потрібно змінити на малий.
Карлос Муньос

0

Використовуй це:

string newName= name[0].ToString().ToLower() + name.Substring(1);

-3

Краще використовувати, String.Concatніж String.Formatякщо ви знаєте, що формат - це не зміна даних, а потрібне просто конкатенація.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.