Ihre Frage ist nicht sehr klar. Was soll der String-Parameter in einer Trimmfunktion genau tun? (Angenommen, Sie beziehen sich nicht auf die obligatorische Syntax 'this string' der Erweiterungsmethode)
asawyer
1
Sie möchten also zwei Funktionen mit derselben Funktionalität wie TrimStart / TrimEnd | Oder möchten Sie eine, die die eingegebenen Zeichen vom Anfang / Ende entfernt?
Blam
Ja, dieselbe Funktionalität wie TrimStart und TrimEnd, akzeptiert jedoch eine Zeichenfolge anstelle eines Zeichens.
Mike Cole
String in .Net hat Trim, TrimEnd und TrimStart. Möchten Sie sie nicht verwenden? oder möchten Sie sehen, wie dies als Lernübung durchgeführt werden kann?
Jwwishart
Antworten:
102
Um alle Vorkommen der (genau übereinstimmenden) Zeichenfolge zu kürzen, können Sie Folgendes verwenden:
TrimStart
publicstaticstringTrimStart(thisstring target, string trimString)
{
if (string.IsNullOrEmpty(trimString)) return target;
string result = target;
while (result.StartsWith(trimString))
{
result = result.Substring(trimString.Length);
}
return result;
}
TrimEnd
publicstaticstringTrimEnd(thisstring target, string trimString)
{
if (string.IsNullOrEmpty(trimString)) return target;
string result = target;
while (result.EndsWith(trimString))
{
result = result.Substring(0, result.Length - trimString.Length);
}
return result;
}
Um eines der Zeichen in trimChars vom Anfang / Ende des Ziels aus zu trimmen (z. B. "foobar'@"@';".TrimEnd(";@'")wird zurückkehren "foobar"), können Sie Folgendes verwenden:
Dies ist keine gute Lösung, da auch eine teilweise Übereinstimmung abgeschnitten wird: "foobartes" .TrimEnd ("test" .ToCharArray ()) führt zu foobar. Imho sollte es nur trimmen, wenn Sie eine genaue Übereinstimmung erhalten. edit: quickfix: füge ein target hinzu.EndsWith (trimChars) check vor dem trimmen
Contra
stimmte zu, das klingt nicht nach dem, was die Operation angefordert hat. Ich war unter der Annahme, dass sie eine bestimmte Saite vom Anfang einer größeren Saite abschneiden wollen. Durch einfaches TrimStarting aller Zeichen in der Zeichenfolge können Fälle entfernt werden, in denen sie nicht genau übereinstimmen.
Tim
2
Danke für den string.ToCharArray()Tipp.
Hamid Sadeghian
5
Ehrlich gesagt sollte der Teil über TrimStart/End(trimChars.ToCharArray());wirklich gelöscht werden. Das wird so gut wie nie wie erwartet funktionieren, außer in einem naiven Test und dann in der Produktion.
Chris Marisic
1
Dies wird für immer wiederholt, wenn Sie trimString == ""auch nicht sicher sind, ob Sie es immer wollen "12123".TimeStart("12") == "3".
smg
13
TrimStart und TrimEnd nehmen eine Reihe von Zeichen auf. Dies bedeutet, dass Sie eine Zeichenfolge wie folgt als char-Array übergeben können:
var trimChars = " .+-";
var trimmed = myString.TrimStart(trimChars.ToCharArray());
Daher sehe ich keine Notwendigkeit für eine Überladung, die einen Zeichenfolgenparameter benötigt.
Wow, das ist peinlich. Ich wusste nicht, dass es so funktioniert. Vielen Dank!
Mike Cole
28
Beachten Sie, dass diese Lösung den Trimmzeichen in beliebiger Reihenfolge entspricht. Zum Beispiel, wenn myString="Sammy"und trimChars="Sam"es wird "y" zurückgeben, aber das erwartete Ergebnis ist "my". Es schneidet also zu viel und betrachtet das Trimmwort nicht als solches.
Matt
Wie @Matt erklärte, ist dieser Weg etwas riskant. Dies geschieht, weil das Trimmen (Start / Ende) ein Array von Zeichen als Argument und nicht als Zeichenfolge verwendet. Anhand dieses Beispiels können Sie auch myString="Sammy"und haben trimChars="SaX"; Dies führt zu "mmy". Stellen Sie sicher, dass dies Ihr gewünschtes Verhalten ist
Andrew vor
11
Ich dachte, die Frage würde versuchen, eine bestimmte Zeichenfolge vom Anfang einer größeren Zeichenfolge aus zu kürzen.
Wenn ich zum Beispiel die Zeichenfolge "hellohellogoodbyehello" hätte und Sie versuchen würden, TrimStart ("hallo") aufzurufen, würden Sie "goodbyehello" zurückbekommen.
In diesem Fall können Sie folgenden Code verwenden:
stringTrimStart(string source, string toTrim)
{
string s = source;
while (s.StartsWith(toTrim))
{
s = s.Substring(toTrim.Length - 1);
}
return s;
}
Dies wäre nicht sehr effizient, wenn Sie viel Schnur schneiden müssten, aber wenn es nur für einige Fälle ist, ist es einfach und erledigt die Arbeit.
Danke, schöner Code. Ich wende nur ein Bit auf sie » if (source == null){return null;}in meiner App. Ich denke, es ist in diesen Fällen eine bessere Wahl.
Leider ist die TrimStart-Methode nicht stark optimiert. In bestimmten Situationen können Sie wahrscheinlich zeichenbasierten Iterationscode schreiben, der diese übertrifft. Dies liegt daran, dass ein Array erstellt werden muss, um TrimStart verwenden zu können.
Allerdings: Benutzerdefinierter Code würde nicht unbedingt ein Array erfordern. Für schnell entwickelte Anwendungen ist die TrimStart-Methode jedoch nützlich.
Und wie kann es umgesetzt werden? Ich denke das war die Frage.
Matt
0
In C # ist keine Funktion integriert - Sie können jedoch eigene Erweiterungen schreiben, die sich genau so verhalten, wie Sie es erwarten.
Beachten Sie, dass Sie mit IndexOf / LastIndexOf auswählen können, ob zwischen Groß- und Kleinschreibung / Kultur unterschieden werden soll oder nicht.
Ich habe auch die Funktion "repetitive Trims" implementiert.
Es gibt eine Funktion TrimStr(..)Umgang mit beiden Ordnungen, plus drei Funktionen Implementierung .TrimStart(...), .TrimEnd(...)und .Trim(..)für die Kompatibilität mit den .NET - Ordnungen:
Beachten Sie, dass TrimStr intern von Trim, TrimStart und TrimEnd verwendet wird.
Matt
Der Unterschied besteht darin, dass Sie mit TrimStr über einen Parameter entscheiden können, ob Sie eine Trimmung vom Anfang oder vom Ende der Zeichenfolge aus wünschen.
Matt
-1
Ich gehe davon aus, dass Sie damit meinen, dass Sie beispielsweise mit der Zeichenfolge "HelloWorld" und dem Aufruf der Funktion zum Trimmen des Starts mit "Hello" "World" erhalten würden. Ich würde argumentieren, dass dies wirklich eine Teilzeichenfolgenoperation ist, da Sie einen Teil der Zeichenfolge bekannter Länge entfernen, anstatt eine Trimmoperation, die eine unbekannte Zeichenfolgenlänge entfernt.
Aus diesem Grund haben wir einige Erweiterungsmethoden mit dem Namen SubstringAfterund erstellt SubstringBefore. Es wäre schön, sie im Framework zu haben, aber sie sind nicht so, dass Sie sie selbst implementieren müssen. Vergessen Sie nicht, einen StringComparisonParameter zu haben und Ordinalals Standard zu verwenden, wenn Sie ihn optional machen.
Wenn Sie eine möchten, die die integrierten Trimmfunktionen aus irgendeinem Grund nicht verwendet, vorausgesetzt, Sie möchten eine Eingabezeichenfolge zum Trimmen verwenden, z. B. "~!" im Wesentlichen das gleiche sein wie das in TrimStart eingebaute mit ['', '~', '!']
Funktion zum Trimmen von Anfang / Ende eines Strings mit einem String-Parameter, jedoch nur einmal (keine Schleife, dieser Einzelfall ist beliebter, Schleife kann mit einem zusätzlichen Parameter hinzugefügt werden, um ihn auszulösen):
Wenn Sie den Ansatz "while-Schleife" implementieren möchten, müssen Sie, wie bereits erwähnt, nach leeren Zeichenfolgen suchen, da diese sonst für immer wiederholt werden können.
Antworten:
Um alle Vorkommen der (genau übereinstimmenden) Zeichenfolge zu kürzen, können Sie Folgendes verwenden:
TrimStart
public static string TrimStart(this string target, string trimString) { if (string.IsNullOrEmpty(trimString)) return target; string result = target; while (result.StartsWith(trimString)) { result = result.Substring(trimString.Length); } return result; }
TrimEnd
public static string TrimEnd(this string target, string trimString) { if (string.IsNullOrEmpty(trimString)) return target; string result = target; while (result.EndsWith(trimString)) { result = result.Substring(0, result.Length - trimString.Length); } return result; }
Um eines der Zeichen in trimChars vom Anfang / Ende des Ziels aus zu trimmen (z. B.
"foobar'@"@';".TrimEnd(";@'")
wird zurückkehren"foobar"
), können Sie Folgendes verwenden:TrimStart
public static string TrimStart(this string target, string trimChars) { return target.TrimStart(trimChars.ToCharArray()); }
TrimEnd
public static string TrimEnd(this string target, string trimChars) { return target.TrimEnd(trimChars.ToCharArray()); }
quelle
string.ToCharArray()
Tipp.TrimStart/End(trimChars.ToCharArray());
wirklich gelöscht werden. Das wird so gut wie nie wie erwartet funktionieren, außer in einem naiven Test und dann in der Produktion.trimString == ""
auch nicht sicher sind, ob Sie es immer wollen"12123".TimeStart("12") == "3"
.TrimStart und TrimEnd nehmen eine Reihe von Zeichen auf. Dies bedeutet, dass Sie eine Zeichenfolge wie folgt als char-Array übergeben können:
var trimChars = " .+-"; var trimmed = myString.TrimStart(trimChars.ToCharArray());
Daher sehe ich keine Notwendigkeit für eine Überladung, die einen Zeichenfolgenparameter benötigt.
quelle
myString="Sammy"
undtrimChars="Sam"
es wird "y" zurückgeben, aber das erwartete Ergebnis ist "my". Es schneidet also zu viel und betrachtet das Trimmwort nicht als solches.myString="Sammy"
und habentrimChars="SaX"
; Dies führt zu"mmy"
. Stellen Sie sicher, dass dies Ihr gewünschtes Verhalten istIch dachte, die Frage würde versuchen, eine bestimmte Zeichenfolge vom Anfang einer größeren Zeichenfolge aus zu kürzen.
Wenn ich zum Beispiel die Zeichenfolge "hellohellogoodbyehello" hätte und Sie versuchen würden, TrimStart ("hallo") aufzurufen, würden Sie "goodbyehello" zurückbekommen.
In diesem Fall können Sie folgenden Code verwenden:
string TrimStart(string source, string toTrim) { string s = source; while (s.StartsWith(toTrim)) { s = s.Substring(toTrim.Length - 1); } return s; }
Dies wäre nicht sehr effizient, wenn Sie viel Schnur schneiden müssten, aber wenn es nur für einige Fälle ist, ist es einfach und erledigt die Arbeit.
quelle
toTrim.length
ohne das-1
Recht sein?Um die gesamte Zeichenfolge abzugleichen und nicht mehrere Teilzeichenfolgen zuzuweisen, sollten Sie Folgendes verwenden:
public static string TrimStart(this string source, string value, StringComparison comparisonType) { if (source == null) { throw new ArgumentNullException(nameof(source)); } int valueLength = value.Length; int startIndex = 0; while (source.IndexOf(value, startIndex, comparisonType) == startIndex) { startIndex += valueLength; } return source.Substring(startIndex); } public static string TrimEnd(this string source, string value, StringComparison comparisonType) { if (source == null) { throw new ArgumentNullException(nameof(source)); } int sourceLength = source.Length; int valueLength = value.Length; int count = sourceLength; while (source.LastIndexOf(value, count, comparisonType) == count - valueLength) { count -= valueLength; } return source.Substring(0, count); }
quelle
if (source == null){return null;}
in meiner App. Ich denke, es ist in diesen Fällen eine bessere Wahl.von dotnetperls.com ,
quelle
In C # ist keine Funktion integriert - Sie können jedoch eigene Erweiterungen schreiben, die sich genau so verhalten, wie Sie es erwarten.
Beachten Sie, dass Sie mit IndexOf / LastIndexOf auswählen können, ob zwischen Groß- und Kleinschreibung / Kultur unterschieden werden soll oder nicht.
Ich habe auch die Funktion "repetitive Trims" implementiert.
Es gibt eine Funktion
TrimStr(..)
Umgang mit beiden Ordnungen, plus drei Funktionen Implementierung.TrimStart(...)
,.TrimEnd(...)
und.Trim(..)
für die Kompatibilität mit den .NET - Ordnungen:Probieren Sie es in DotNetFiddle aus
public static class Extension { public static string TrimStr(this string str, string trimStr, bool trimEnd = true, bool repeatTrim = true, StringComparison comparisonType = StringComparison.OrdinalIgnoreCase) { int strLen; do { if (!(str ?? "").EndsWith(trimStr)) return str; strLen = str.Length; { if (trimEnd) { var pos = str.LastIndexOf(trimStr, comparisonType); if ((!(pos >= 0)) || (!(str.Length - trimStr.Length == pos))) break; str = str.Substring(0, pos); } else { var pos = str.IndexOf(trimStr, comparisonType); if (!(pos == 0)) break; str = str.Substring(trimStr.Length, str.Length - trimStr.Length); } } } while (repeatTrim && strLen > str.Length); return str; } // the following is C#6 syntax, if you're not using C#6 yet // replace "=> ..." by { return ... } public static string TrimEnd(this string str, string trimStr, bool repeatTrim = true, StringComparison comparisonType = StringComparison.OrdinalIgnoreCase) => TrimStr(str, trimStr, true, repeatTrim, comparisonType); public static string TrimStart(this string str, string trimStr, bool repeatTrim = true, StringComparison comparisonType = StringComparison.OrdinalIgnoreCase) => TrimStr(str, trimStr, false, repeatTrim, comparisonType); public static string Trim(this string str, string trimStr, bool repeatTrim = true, StringComparison comparisonType = StringComparison.OrdinalIgnoreCase) => str.TrimStart(trimStr, repeatTrim, comparisonType) .TrimEnd(trimStr, repeatTrim, comparisonType); }
Jetzt können Sie es einfach so verwenden
Console.WriteLine("Sammy".TrimEnd("my")); Console.WriteLine("moinmoin gibts gips? gips gibts moin".TrimStart("moin", false)); Console.WriteLine("moinmoin gibts gips? gips gibts moin".Trim("moin").Trim());
das schafft die Ausgabe
quelle
Ich gehe davon aus, dass Sie damit meinen, dass Sie beispielsweise mit der Zeichenfolge "HelloWorld" und dem Aufruf der Funktion zum Trimmen des Starts mit "Hello" "World" erhalten würden. Ich würde argumentieren, dass dies wirklich eine Teilzeichenfolgenoperation ist, da Sie einen Teil der Zeichenfolge bekannter Länge entfernen, anstatt eine Trimmoperation, die eine unbekannte Zeichenfolgenlänge entfernt.
Aus diesem Grund haben wir einige Erweiterungsmethoden mit dem Namen
SubstringAfter
und erstelltSubstringBefore
. Es wäre schön, sie im Framework zu haben, aber sie sind nicht so, dass Sie sie selbst implementieren müssen. Vergessen Sie nicht, einenStringComparison
Parameter zu haben undOrdinal
als Standard zu verwenden, wenn Sie ihn optional machen.quelle
Wenn Sie eine möchten, die die integrierten Trimmfunktionen aus irgendeinem Grund nicht verwendet, vorausgesetzt, Sie möchten eine Eingabezeichenfolge zum Trimmen verwenden, z. B. "~!" im Wesentlichen das gleiche sein wie das in TrimStart eingebaute mit ['', '~', '!']
public static String TrimStart(this string inp, string chars) { while(chars.Contains(inp[0])) { inp = inp.Substring(1); } return inp; } public static String TrimEnd(this string inp, string chars) { while (chars.Contains(inp[inp.Length-1])) { inp = inp.Substring(0, inp.Length-1); } return inp; }
quelle
Funktion zum Trimmen von Anfang / Ende eines Strings mit einem String-Parameter, jedoch nur einmal (keine Schleife, dieser Einzelfall ist beliebter, Schleife kann mit einem zusätzlichen Parameter hinzugefügt werden, um ihn auszulösen):
public static class BasicStringExtensions { public static string TrimStartString(this string str, string trimValue) { if (str.StartsWith(trimValue)) return str.TrimStart(trimValue.ToCharArray()); //otherwise don't modify return str; } public static string TrimEndString(this string str, string trimValue) { if (str.EndsWith(trimValue)) return str.TrimEnd(trimValue.ToCharArray()); //otherwise don't modify return str; } }
Wenn Sie den Ansatz "while-Schleife" implementieren möchten, müssen Sie, wie bereits erwähnt, nach leeren Zeichenfolgen suchen, da diese sonst für immer wiederholt werden können.
quelle