643 Stimmen

Den ersten Buchstaben einer Zeichenkette groß schreiben (mit maximaler Leistung)

Ich habe eine DetailsView mit einer TextBox und ich möchte die Eingangsdaten sein immer gespeichert mit dem erster Buchstabe in Großbuchstaben .

Exemple :

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

Wie kann ich das erreichen? Leistungsmaximierung ?


Hinweis :

Ausgehend von den Antworten und den Kommentaren unter den Antworten denken viele, dass es hier um die Kapitalisierung geht alle Wörter in der Zeichenkette. z.B. => Red House Ist es nicht, aber wenn es das ist, was Sie suchen suchen Sie nach einer der Antworten, in der TextInfo 's ToTitleCase Methode. (Anmerkung: Diese Antworten sind falsch für die tatsächlich gestellte Frage). Siehe TextInfo.ToTitleCase Dokumentation für Vorbehalte (berührt keine Wörter in Großbuchstaben - sie werden als Akronyme betrachtet; kann Buchstaben in der Mitte von Wörtern kleinschreiben, die nicht kleingeschrieben werden sollten, z. B. "McDonald" "Mcdonald"; nicht garantiert, dass alle kulturspezifischen Feinheiten in Bezug auf Großschreibregeln berücksichtigt werden).


Hinweis :

Die Frage lautet zweideutig die Frage, ob die Buchstaben nach dem ersten Buchstaben gezwungen a Kleinschreibung . Die akzeptierte Antwort geht davon aus, dass nur der erste Buchstabe sollte geändert werden . Wenn Sie Folgendes erzwingen wollen alle Buchstaben der Zeichenkette außer dem ersten klein geschrieben werden soll, suchen Sie nach einer Antwort, die ToLower y die nicht ToTitleCase enthalten .

10 Stimmen

@Bobby: Es handelt sich nicht um ein Duplikat: Im OP wird darum gebeten, den ersten Buchstaben einer Zeichenfolge groß zu schreiben, in der Frage im Link wird der erste Buchstabe jedes Wortes groß geschrieben.

2 Stimmen

@GvS: Die erste Antwort lautet sehr detailliert und der erste Code-Block ist genau wonach er sucht. Auch der Unterschied zwischen der Großschreibung aller Wörter und der Großschreibung nur des ersten Wortes ist nur eine Schleife.

2 Stimmen

Aber Sie sagten, und ich zitiere: "Machen Sie den ersten Buchstaben JEDES WORTES groß". Warum also "rotes Haus" --> "Rotes Haus"? Warum ist das "h" von "Haus" kein Großbuchstabe?

40voto

Kobi Punkte 129985

Für den ersten Buchstaben, mit Fehlerprüfung:

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

Und hier ist das Gleiche als praktische Erweiterung

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

0 Stimmen

Sauberer Ansatz. Ich danke Ihnen!

19voto

l33t Punkte 15267

使用する string.Create() und die Vermeidung des throw Schlüsselwort in unserer Methode (ja, Sie haben richtig gelesen), können wir die Marzells Antwort einen Schritt weiter. Außerdem kann meine Methode Zeichenketten beliebiger Länge verarbeiten (z. B. mehrere Megabyte Text).

public static string L33t(this string s)
{
    static void ThrowError() => throw new ArgumentException("There is no first letter");

    if (string.IsNullOrEmpty(s))
        ThrowError();                      // No "throw" keyword to avoid costly IL

    return string.Create(s.Length, s, (chars, state) =>
    {
        state.AsSpan().CopyTo(chars);      // No slicing to save some CPU cycles
        chars[0] = char.ToUpper(chars[0]);
    });
}

Leistung

Hier sind die Zahlen für Benchmarks, die auf .NET Core 3.1.7, 64 Bit . Ich habe eine längere Zeichenfolge hinzugefügt, um die Kosten für zusätzliche Kopien zu ermitteln.

Methode

Daten

Mittlere

Fehler

StdDev

Median

L33t

rot

8.545 ns

0,4612 ns

1,3308 ns

8,075 ns

Marcell

rot

9.153 ns

0,3377 ns

0,9471 ns

8.946 ns

L33t

rotes Haus

7.715 ns

0,1741 ns

0,4618 ns

7.793 ns

Marcell

rotes Haus

10.537 ns

0,5002 ns

1,4351 ns

10.377 ns

L33t

rotes r(...)haus [89]

11.121 ns

0,6774 ns

1,9106 ns

10.612 ns

Marcell

rotes r(...)haus [89]

16.739 ns

0,4468 ns

1,3033 ns

16,853 ns

Vollständiger Prüfcode

using System;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;

namespace CorePerformanceTest
{
    class Program
    {
        static void Main(string[] args)
        {
            var summary = BenchmarkRunner.Run<StringUpperTest>();
        }
    }

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

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

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

    internal static class StringExtensions
    {
        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);
        }

        public static string L33t(this string s)
        {
            static void ThrowError() => throw new ArgumentException("There is no first letter");

            if (string.IsNullOrEmpty(s))
                ThrowError(); // IMPORTANT: Do not "throw" here!

            return string.Create(s.Length, s, (chars, state) =>
            {
                state.AsSpan().CopyTo(chars);
                chars[0] = char.ToUpper(chars[0]);
            });
        }
    }
}

Bitte lassen Sie es mich wissen, wenn Sie es noch schneller machen können!

1 Stimmen

Warum kann man das Schlüsselwort throw nicht nach string.IsNullOrEmpty (WICHTIG: Hier nicht "werfen"!)?

2 Stimmen

Vous peut verwenden Sie die throw Schlüsselwort, aber seine bloße Existenz verhindert bestimmte Compiler-Optimierungen, wie z.B. Inlining. Sie können das Beispiel mit und ohne dieses Schlüsselwort ausführen, und Sie werden sehen, dass es sich tatsächlich auf die Leistung auswirkt.

16voto

Marcell Toth Punkte 2901

Diese Frage bezieht sich auf Leistungsmaximierung habe ich angenommen Darrens Version zu verwenden Span s, was den Müll reduziert und die Geschwindigkeit um etwa 10 % erhöht.

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

Leistung

Methode

Daten

Mittlere

Fehler

StdDev

Carlos

rot

107,29 ns

2.2401 ns

3,9234 ns

Darren

rot

30,93 ns

0,9228 ns

0,8632 ns

Marcell

rot

26,99 ns

0,3902 ns

0,3459 ns

Carlos

rotes Haus

106,78 ns

1,9713 ns

1,8439 ns

Darren

rotes Haus

32,49 ns

0,4253 ns

0,3978 ns

Marcell

rotes Haus

27,37 ns

0,3888 ns

0,3637 ns

Vollständiger Prüfcode

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

}

4 Stimmen

Wahrscheinlich sollten Sie sich gegen überlange Strings absichern. stackalloc wird den Stapel zerschlagen, wenn Sie mehr als ~1MB an Zeichen haben.

0 Stimmen

Bitte beachten Sie meine verbesserte Antwort , mit string.Create() .

13voto

Taras Alenin Punkte 7676
public static string ToInvarianTitleCase(this string self)
{
    if (string.IsNullOrWhiteSpace(self))
    {
        return self;
    }

    return CultureInfo.InvariantCulture.TextInfo.ToTitleCase(self);
}

9voto

Die schnellste Methode:

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

Die Tests zeigen die nächsten Ergebnisse (Zeichenkette mit 1.0000.000 Zeichen als Eingabe):

Testergebnisse

4 Stimmen

Ich empfehle die Rückgabe s wenn der Parameter null oder leer ist.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X