BestPractice - Przekształć pierwszy znak ciągu w małe litery


136

Chciałbym mieć metodę, która przekształca pierwszy znak ciągu w małe litery.

Moje podejścia:

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

Jakie byłoby Twoje podejście?

Odpowiedzi:


239

Użyłbym prostej konkatenacji:

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

Pierwsze rozwiązanie nie jest zoptymalizowane, ponieważ string.Formatjest wolne i nie potrzebujesz go, jeśli masz format, który nigdy się nie zmieni. Generuje również dodatkowy ciąg, który zamienia literę na małe litery, co nie jest potrzebne.

Podejście z „+ 32” jest brzydkie / niemożliwe do utrzymania, ponieważ wymaga znajomości przesunięć wartości znaków ASCII. Będzie również generować nieprawidłowe dane wyjściowe z danymi Unicode i znakami symboli ASCII.


4
zrobiłbym to:char.ToLower(name[0]).ToString() + name.Substring(1)
Andrey

7
@Rookian: +operator jest powolny, gdy łączysz wiele ciągów. W takim przypadku a StringBuilderdziałałby znacznie lepiej. Jednak +jest znacznie szybszy niż string.Format. Użyj tego ostatniego, gdy faktycznie musisz coś sformatować (np. Wyświetlanie liczb całkowitych, podwójnych lub dat).
Dirk Vollmar

6
@ 0x03: jest wolny tylko wtedy, gdy wielokrotnie konkatenujesz wiele ciągów. Jeśli połączysz je wszystkie w jednej operacji, +operator nie jest wcale wolny, ponieważ kompilator zamienia go na a String.Concat(jednak String.Joinjest szybszy niż String.Concatz jakiegoś głupiego powodu).
Thorarin

2
Szybsza metoda jest następująca: publiczny ciąg statyczny ToFirstLetterLower (tekst w postaci ciągu znaków) {var charArray = text.ToCharArray (); charArray [0] = char.ToLower (charArray [0]); return new string (charArray); }
Matteo Migliore

2
Użyłem rozszerzenia 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); } na podstawie komentarza @ MatteoMigliore.
KregHEk

64

W zależności od sytuacji może być potrzebne trochę programowania obronnego:

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

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

ifOświadczenie zapobiega także nowy ciąg z budowane jeśli nie będzie zresztą zmieniło. Zamiast tego możesz chcieć, aby metoda zakończyła się niepowodzeniem przy zerowym wejściu i wyrzucić ArgumentNullException.

Jak już wspomnieli ludzie, używanie String.Formatdo tego jest przesadą.


Popraw mnie, jeśli się mylę, ale str.Substring (1) zwróci symbol na pozycji 1, ponieważ liczba dla tej metody nie jest wskazana. więc będziesz miał znak [0] w małych literach + znak na pozycji 1. Wolałem więc usunąć jeden znak zaczynając od pierwszego znaku w ciągu. Wynikiem jest ciąg bez pierwszej litery. Następnie dodam ten ciąg do pierwszego znaku, który jest konwertowany na małe litery
fedotoves

3
@ B-Rain:
uważaj

7

Na wszelki wypadek pomoże to każdemu, kto natknie się na tę odpowiedź.

Myślę, że byłoby to najlepsze jako metoda rozszerzająca, wtedy możesz ją wywołać za pomocą 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

Mój jest

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

3
Jestem ciekawy, dlaczego val.Remove? Wydaje mi się to trochę sprzeczne z intuicją.
Thorarin

@Thorarin oczywiście dlatego, że chcesz usunąć pierwszy znak (ponieważ dodajesz wersję z małymi literami z przodu)
Riki

2

Podoba mi się zaakceptowana odpowiedź, ale oprócz sprawdzenia string.IsNullOrEmptychciałbym również sprawdzić, czy Char.IsLower(name[1])na wypadek, gdybyś miał do czynienia ze skrótem. Np. Nie chciałbyś, aby „AIDS” stał się „AIDS”.


8
IMO jest to odpowiedzialność rozmówcy
onof

1

Najszybsze rozwiązanie, jakie znam, bez nadużywania 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

Połączyłem kilka i uczyniłem z niego przedłużenie łańcuchowe. Dodano zwarcie na białych znakach i nieliterach.

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

Jest to mała metoda rozszerzenia wykorzystująca najnowszą składnię i poprawne walidacje

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
Nie jestem pewien, czy wyrzucenie wyjątku byłoby najlepszym rozwiązaniem. Jeśli ciąg jest pusty lub pusty, po prostu zwróć pusty lub pusty ciąg.
R. de Veen

Jeśli String ma wartość null lub jest pusty, operacja nie ma sensu, ponieważ nie ma pierwszego znaku, który można zmienić na małe litery.
Carlos Muñoz

0

Użyj tego:

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

-3

Lepiej jest używać, String.Concatniż String.Formatjeśli wiesz, że format nie jest zmianą danych, a pożądane jest po prostu połączenie.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.