535 Stimmen

Wie kann ich eine .NET-Zeichenkette abschneiden?

Ich möchte eine Zeichenkette so abschneiden, dass sie nicht länger als ein bestimmter Wert ist. Ich schreibe in eine Datenbanktabelle und möchte sicherstellen, dass die Werte, die ich schreibe, die Einschränkung des Datentyps der Spalte erfüllen.

Es wäre zum Beispiel schön, wenn ich Folgendes schreiben könnte:

string NormalizeLength(string value, int maxLength)
{
    return value.Substring(0, maxLength);
}

Leider führt dies zu einer Ausnahme, da maxLength im Allgemeinen die Grenzen der Zeichenfolge überschreitet value . Natürlich könnte ich eine Funktion wie die folgende schreiben, aber ich hatte gehofft, dass so etwas bereits existiert.

string NormalizeLength(string value, int maxLength)
{
    return value.Length <= maxLength ? value : value.Substring(0, maxLength);
} 

Wo ist die schwer fassbare API, die diese Aufgabe erfüllt? Gibt es eine?

31 Stimmen

Für das Protokoll, Strings sind unveränderlich Sie können nicht truncate Sie können nur eine abgeschnittene Kopie von ihnen zurück. Ich weiß, das ist pingelig.

3 Stimmen

@John Weldon: Das ist wahrscheinlich der Grund, warum die Memberfunktion nicht existiert - sie folgt nicht der Semantik des Datentyps. Eine kleine Anmerkung am Rande, StringBuilder können Sie durch Verkürzung der Länge abschneiden, aber Sie müssen immer noch die Längenprüfung durchführen, um eine Verbreiterung der Zeichenkette zu vermeiden.

1 Stimmen

Unabhängig davon, für welche Lösung Sie sich entscheiden, sollten Sie vor dem Aufruf von Substring oder dem Zugriff auf die Length-Eigenschaft eine Prüfung auf eine Null-Zeichenkette hinzufügen.

4voto

Ed B Punkte 746

Ich weiß, es gibt eine Tonne von Antworten hier bereits, aber dies ist die, die ich mit gegangen bin, die sowohl Null-Zeichenfolgen und die Situation, wo die Länge übergeben in negativ ist behandelt:

public static string Truncate(this string s, int length)
{
    return string.IsNullOrEmpty(s) || s.Length <= length ? s 
        : length <= 0 ? string.Empty 
        : s.Substring(0, length);
}

3voto

K. R. Punkte 1102

Nur für den Fall, dass es hier nicht genug Antworten gibt, hier ist meine :)

public static string Truncate(this string str, 
                              int totalLength, 
                              string truncationIndicator = "")
{
    if (string.IsNullOrEmpty(str) || str.Length < totalLength) 
        return str;

    return str.Substring(0, totalLength - truncationIndicator.Length) 
           + truncationIndicator;
}

zu verwenden:

"I use it like this".Truncate(5,"~")

3voto

Edward Brey Punkte 37840

Die beliebte Bibliothek Humanisierer hat eine abschneiden Methode. Zur Installation mit NuGet:

Install-Package Humanizer

3voto

PSXGamerPro1 Punkte 103

Alle anderen Antworten berücksichtigen nicht die Span's, die leistungsfähiger sind als die Substring des Stringtyps in .NET

Falls Sie es noch nicht wissen, es gibt eine Version von System.Memory (die Span, ReadOnlySpan, Memory und ReadOnlyMemory für Fälle wie diesen bereitstellt:

Eine einfache Umsetzung könnte also wie folgt aussehen:

public static string Truncate(this string value, int maxLength)
{
    if (!string.IsNullOrEmpty(value) && value.Length > maxLength)
    {
        return value.AsSpan(0, maxLength).ToString(); /* Note the use of AsSpan instead of Substring. */
    }

    return value;
}

Die Methode könnte theoretisch so gestaltet werden, dass sie Span<char> zu verwenden, um die Zuweisung einer neuen Zeichenkette mit Hilfe der ToString() Mitglied von Span<T> .

Die BCL selbst verwendet intern Span's, ReadOnlySpan's, Memory's und ReadOnlyMemory's, wo dies möglich ist, um Probleme zu vermeiden und den Code zu optimieren, insbesondere wenn Sie Arrays kompilieren, die zur Kompilierzeit bekannt sind, und daher eine Eigenschaft verwenden, die das neu erstellte Array als ReadOnlySpan<byte> tatsächlich den Code zur Laufzeit optimiert, da das JIT dann nicht die memcpy auf die Daten und verwendet es stattdessen, da es nur einen Span zurückgibt und als solches ein Fenster zu den Daten ist, die bereits vor der Zeit zugewiesen sind, was zu:

  1. abzüglich der Zuweisungen.
  2. Weniger Zeitaufwand für die Zuweisung.
  3. macht den Code insgesamt schneller einsetzbar.

2voto

SoftDev Punkte 1084

Um der (Über-)Komplexität willen füge ich meine überladene Version hinzu, die die letzten 3 Zeichen durch eine Ellipse in Bezug auf den maxLength-Parameter ersetzt.

public static string Truncate(this string value, int maxLength, bool replaceTruncatedCharWithEllipsis = false)
{
    if (replaceTruncatedCharWithEllipsis && maxLength <= 3)
        throw new ArgumentOutOfRangeException("maxLength",
            "maxLength should be greater than three when replacing with an ellipsis.");

    if (String.IsNullOrWhiteSpace(value)) 
        return String.Empty;

    if (replaceTruncatedCharWithEllipsis &&
        value.Length > maxLength)
    {
        return value.Substring(0, maxLength - 3) + "...";
    }

    return value.Substring(0, Math.Min(value.Length, maxLength)); 
}

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