Der beste Weg, um Leerzeichen in einer String.Split-Operation anzugeben

242

Ich teile eine Zeichenfolge basierend auf Leerzeichen wie folgt auf:

string myStr = "The quick brown fox jumps over the lazy dog";

char[] whitespace = new char[] { ' ', '\t' };
string[] ssizes = myStr.Split(whitespace);

Es ist lästig, das char [] -Array überall in meinem Code zu definieren. Ich möchte dies tun. Gibt es eine effizientere Methode, bei der kein Zeichenarray erstellt werden muss (das fehleranfällig ist, wenn es an verschiedenen Stellen kopiert wird)?

John Saunders
quelle
1
macht das: myStr.Split (''); nicht arbeiten?
Woolagaroo
4
Wenn ich das richtig verstehe, wird nur nach einem Leerzeichen
Siehe auch mögliche Duplikate, aber diese späteren Antworten haben SplitStringOptions. stackoverflow.com/questions/1562981/…
goodeye

Antworten:

469

Wenn Sie nur anrufen:

string[] ssize = myStr.Split(null);

oder:

string[] ssize = myStr.Split(new char[0]);

dann wird angenommen, dass Leerraum das Teilungszeichen ist. Auf der string.Split(char[])Dokumentationsseite der Methode .

Wenn der Trennzeichenparameter nullkeine Zeichen enthält oder enthält, werden Leerzeichen als Trennzeichen angenommen. Leerzeichen werden durch den Unicode-Standard definiert und geben zurück, truewenn sie an die Char.IsWhiteSpaceMethode übergeben werden.

Lesen Sie immer, immer, immer die Dokumentation!

Jason
quelle
2
Das Problem beim Teilen nach Leerzeichen besteht darin, dass Sie nicht wissen, welches Leerzeichen Sie zurücksetzen sollen, wenn Sie es erneut zusammensetzen müssen.
Ross Presser
19
(char[])nullist etwas besser, da es vermieden wird, ein neues Objekt zu erstellen. (Sie können nullmit keiner der optionsÜberladungen verwenden).
Artfunkel
5
@ RossPresser: Das Zusammensetzen eines Strings ist ein völlig anderes Problem, daher würde ich nicht sagen, dass dies hier ein Problem ist. Aber wenn Sie nur die Saite wieder genau so zusammensetzen müssen, wie sie vorher war, behalten Sie vielleicht besser das Original.
stakx - nicht mehr beitragen
4
Dumme Frage, aber wenn Sie verwenden null, müssen Sie noch die angeben StringSplitOption.RemoveEmptyEntriesoder werden sie standardmäßig ignoriert?
Yu_ominae
2
@ RossPresser: Da String.Split keinen Mechanismus zum Verfolgen der Zeichen bietet, die zum Teilen des Strings verwendet werden, ist Ihre Beobachtung nicht relevant: Mit String.Split kann man nicht das erreichen, was Sie suchen, sodass andere Fragen und Antworten erforderlich sind.
ToolmakerSteve
207

Ja, hier ist noch eine Antwort erforderlich!

Alle bisherigen Lösungen befassen sich mit dem eher begrenzten Bereich der kanonischen Eingabe : einem einzelnen Leerzeichen zwischen den Elementen (obwohl @cherno die Spitze des Hutes ist, um zumindest das Problem zu erwähnen). Aber ich vor , dass in allen , aber die dunkelsten Szenarien, Splitting alle diese sollten identische Ergebnisse liefern:

string myStrA = "The quick brown fox jumps over the lazy dog";
string myStrB = "The  quick  brown  fox  jumps  over  the  lazy  dog";
string myStrC = "The quick brown fox      jumps over the lazy dog";
string myStrD = "   The quick brown fox jumps over the lazy dog";

String.Split(in einer der in den anderen Antworten hier gezeigten Geschmacksrichtungen) funktioniert einfach nicht gut, es sei denn, Sie fügen die RemoveEmptyEntriesOption mit einer der folgenden Optionen hinzu:

myStr.Split(new char[0], StringSplitOptions.RemoveEmptyEntries)
myStr.Split(new char[] {' ','\t'}, StringSplitOptions.RemoveEmptyEntries)

Wie die Abbildung zeigt, führt das Weglassen der Option zu vier verschiedenen Ergebnissen (mit A, B, C und D bezeichnet) im Vergleich zum Einzelergebnis aller vier Eingaben, wenn Sie Folgendes verwenden RemoveEmptyEntries:

String.Split vs Regex.Split

Wenn Sie keine Optionen verwenden möchten, verwenden Sie einfach die Regex-Alternative :-)

Regex.Split(myStr, @"\s+").Where(s => s != string.Empty)
Michael Sorens
quelle
4
Ich denke, @RossPresser, dass dies durch mein Qualifikationsmerkmal "unter allen außer den dunkelsten Szenarien" abgedeckt wird, denn selbst wenn ich die Elemente neu kombinieren möchte, würde es mir schwer fallen, einen Fall zu haben, in dem mir mehrere Leerzeichen wichtig sind. Ich würde eine kanonische Form wollen - ein Leerzeichen zwischen jedem. Ich bin also respektvoll anderer Meinung - es wäre eher "selten falsch" als "normalerweise falsch".
Michael Sorens
1
CapitalizeEveryWord("This is line one.\n \nThis is line three.")
Ross Presser
3
Wenn Sie wirklich denken, dass dies dunkel ist, müssen wir uns wohl darauf einigen, nicht zuzustimmen, aber wenn ich diese Funktion aus meiner Software herauslasse, würde ich meinen Job verlieren. Benutzer möchten, dass ihre Inhalte so aussehen, wie sie es möchten.
Ross Presser
4
Dies sollte eine akzeptierte Antwort sein, da sie viel vollständiger ist.
Dennis
1
Ich frage mich, warum Sie .Where(s => s != string.Empty)dem Regex hinzugefügt haben . Da Sie \s+(eine beliebige Anzahl von Leerzeichen) angeben, darf kein leeres Element dazwischen liegen.
Jack Miller
44

Laut Dokumentation :

Wenn der Trennzeichenparameter null ist oder keine Zeichen enthält, werden Leerzeichen als Trennzeichen angenommen. Leerzeichen werden vom Unicode-Standard definiert und geben true zurück, wenn sie an die Char.IsWhiteSpace-Methode übergeben werden.

Rufen Sie einfach myStr.Split();an. Sie müssen nichts übergeben, da das Trennzeichen ein paramsArray ist.

ageektrapped
quelle
11

Warum benutzt du nicht?:

string[] ssizes = myStr.Split(' ', '\t');
Renatas M.
quelle
2
Es gibt keine Split-Überlastung, die zwei Zeichen benötigt.
Takrl
1
@takrl: Schauen Sie hier öffentliche Zeichenfolge [] Split (params char [] Trennzeichen) .NET v2
Renatas M.
Ja, dies erfordert ein Zeichenarray. Ihr Code-Snippet besteht aus zwei einzelnen Zeichen.
Takrl
15
@takrl: Weißt du was das Schlüsselwort params ist ???
Renatas M.
Ziemlich cool, +1 dafür. Wahrscheinlich wusste es auch die Person, die abgelehnt hat, nicht.
Takrl
3

Beachten Sie, dass benachbarte Leerzeichen auch bei Verwendung NICHT als einzelnes Trennzeichen behandelt werden String.Split(null). Wenn eines Ihrer Token durch mehrere Leerzeichen oder Tabulatoren getrennt ist, werden leere Zeichenfolgen in Ihrem Array zurückgegeben.

Aus der Dokumentation:

Jedes Trennelement definiert ein separates Trennzeichen. Wenn zwei Trennzeichen nebeneinander liegen oder am Anfang oder Ende dieser Instanz ein Trennzeichen gefunden wird, enthält das entsprechende Array-Element Leer.

cherno
quelle
2

Also nicht kopieren und einfügen! Extrahieren Sie eine Funktion zum Teilen und verwenden Sie sie erneut.

public static string[] SplitWhitespace (string input)
{
    char[] whitespace = new char[] { ' ', '\t' };
    return input.Split(whitespace);
}

Die Wiederverwendung von Code ist dein Freund.

Tim Rogers
quelle
1

Sie können verwenden

var FirstString = YourString.Split (). First ();

String teilen.

Haxer
quelle
0

Kannst du es nicht inline machen?

var sizes = subject.Split(new char[] { ' ', '\t' });

Andernfalls könnten Sie, wenn Sie genau dies häufig tun, immer eine Konstante oder etwas erstellen, das dieses char-Array enthält.

Wie andere angemerkt haben, können Sie laut Dokumentation auch nullein leeres Array verwenden. Wenn Sie dies tun, werden automatisch Leerzeichen verwendet.

var sizes = subject.Split(null);
Svish
quelle
0

Wenn das Wiederholen des gleichen Codes das Problem ist, schreiben Sie eine Erweiterungsmethode in die String-Klasse, die die Aufteilungslogik kapselt.

Xhalent
quelle
1
Dies beantwortet die Frage leider nicht wirklich.
p.campbell
p. Campbell: Ja, das tut es: OP hat nach einer Lösung gefragt, bei der das Zeichenarray nicht überall kopiert werden muss. Eine naheliegende Lösung besteht darin, eine Funktion für die Ausführung der Aufgabe zu erstellen. Diese Antwort weist darauf hin, dass eine solche Funktion eine Erweiterungsmethode sein könnte. (Die Antwort könnte verbessert werden, indem Sie den Code zeigt , dies zu tun ...)
ToolmakerSteve