Meilleure façon de spécifier un espace dans une opération String.Split

243

Je divise une chaîne en fonction de l'espace blanc comme suit:

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

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

Il est fastidieux de définir le tableau char [] partout dans mon code, je veux le faire. Existe-t-il un moyen plus efficace qui ne nécessite pas la création du tableau de caractères (qui est sujet à erreur s'il est copié à différents endroits)?

John Saunders
la source
1
fait ceci: myStr.Split (''); ne fonctionne pas?
woolagaroo
4
Si je comprends bien, cela ne cherchera qu'un espace, pas un espace générique
Voir également les doublons possibles, mais ces réponses ultérieures ont SplitStringOptions. stackoverflow.com/questions/1562981/…
goodeye

Réponses:

469

Si vous appelez simplement:

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

ou:

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

alors l'espace blanc est supposé être le caractère de division. Depuis la string.Split(char[])page de documentation de la méthode .

Si le paramètre séparateur est nullou ne contient aucun caractère, les caractères d'espace blanc sont supposés être les délimiteurs. Les caractères d'espacement sont définis par la norme Unicode et retournent trues'ils sont transmis à la Char.IsWhiteSpaceméthode.

Toujours, toujours, toujours lire la documentation!

Jason
la source
2
Le problème avec la division par espace blanc est que si vous devez le reconstituer, vous ne savez pas quel caractère d'espace blanc à remettre.
Ross Presser
19
(char[])nullest légèrement meilleur car il évite de créer un nouvel objet. (Vous ne pouvez pas utiliser nullavec l'une des optionssurcharges).
Artfunkel
5
@ RossPresser: Remettre une chaîne en place est un problème complètement différent, donc je ne dirais pas que c'est un problème ici. Mais si tout ce que vous avez à faire est de remonter la chaîne exactement comme avant, il vaut peut-être mieux conserver l'original.
stakx - ne contribue plus
4
Question stupide, mais si vous utilisez null, devez-vous toujours spécifier le StringSplitOption.RemoveEmptyEntriesou sont-ils ignorés par défaut?
yu_ominae
2
@RossPresser: Étant donné que String.Split ne fournit aucun mécanisme pour garder une trace des caractères utilisés pour fractionner la chaîne, votre observation n'est pas pertinente: on ne peut pas réaliser ce que vous recherchez en utilisant String.Split, ce qui nécessite une autre Q&R.
ToolmakerSteve
207

Oui, il y a besoin d'une réponse de plus ici!

Toutes les solutions jusqu'à présent concernent le domaine plutôt limité de l' entrée canonique , à savoir: un seul caractère d'espacement entre les éléments (bien que la pointe du chapeau à @cherno pour au moins mentionner le problème). Mais je soumets que dans tous les scénarios, sauf les plus obscurs, le fractionnement de tous ces éléments devrait donner des résultats identiques:

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(dans l'une des saveurs présentées dans les autres réponses ici) ne fonctionne tout simplement pas bien, sauf si vous associez l' RemoveEmptyEntriesoption à l'une de ces options:

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

Comme le montre l'illustration, l'omission de l'option donne quatre résultats différents (étiquetés A, B, C et D) par rapport au résultat unique des quatre entrées lorsque vous utilisez RemoveEmptyEntries:

String.Split vs Regex.Split

Bien sûr, si vous n'aimez pas utiliser les options, utilisez simplement l'alternative regex :-)

Regex.Split(myStr, @"\s+").Where(s => s != string.Empty)
Michael Sorens
la source
4
Je pense, @RossPresser, que cela est couvert par mon qualificatif "dans tous les scénarios, sauf les plus obscurs", car même si je voulais recombiner les éléments, j'aurais du mal à avoir un cas où je me soucierais de plusieurs espaces. Je voudrais une forme canonique - un espace entre chacun. Je suis donc respectueusement en désaccord - ce serait "rarement faux" plutôt que "généralement faux".
Michael Sorens
1
CapitalizeEveryWord("This is line one.\n \nThis is line three.")
Ross Presser
3
Si vous pensez vraiment que c'est obscur, alors je suppose que nous devrons accepter d'être en désaccord, mais si je laissais cette fonction hors de mon logiciel, je perdrais mon emploi. Les utilisateurs aiment que leur contenu ressemble à ce qu'ils veulent.
Ross Presser
4
Cela devrait être une réponse acceptée, car elle est beaucoup plus complète.
Dennis
1
Je me demande pourquoi vous avez ajouté .Where(s => s != string.Empty)au Regex. Puisque vous spécifiez \s+(n'importe quel nombre d'espaces) il ne peut y avoir d'élément vide entre les deux.
Jack Miller
44

Selon la documentation :

Si le paramètre séparateur est nul ou ne contient aucun caractère, les caractères d'espace blanc sont supposés être les délimiteurs. Les caractères d'espacement sont définis par la norme Unicode et retournent true s'ils sont transmis à la méthode Char.IsWhiteSpace.

Il suffit donc d'appeler myStr.Split();Il n'est pas nécessaire de passer quoi que ce soit car le séparateur est un paramstableau.

ageektrapped
la source
11

Pourquoi n'utilisez-vous pas?:

string[] ssizes = myStr.Split(' ', '\t');
Renatas M.
la source
2
Il n'y a pas de surcharge Split qui prend deux caractères.
takrl
1
@takrl: Regardez ici la chaîne publique [] Split (séparateur de paramètres param []) .NET v2
Renatas M.
Oui, cela prend un tableau de caractères. Votre extrait de code transmet deux caractères simples.
takrl
15
@takrl: savez-vous quel mot-clé params est ???
Renatas M.
Assez cool, +1 pour ça. Probablement que la personne qui a downvoté ne le savait pas non plus.
takrl
3

Notez que les espaces adjacents ne seront PAS traités comme un seul délimiteur, même lors de l'utilisation String.Split(null). Si l'un de vos jetons est séparé par plusieurs espaces ou tabulations, vous obtiendrez des chaînes vides retournées dans votre tableau.

De la documentation:

Chaque élément de séparateur définit un caractère de délimiteur distinct. Si deux délimiteurs sont adjacents, ou si un délimiteur est trouvé au début ou à la fin de cette instance, l'élément de tableau correspondant contient Empty.

cherno
la source
2

Alors ne copiez pas et ne collez pas! Extraire une fonction pour effectuer votre fractionnement et la réutiliser.

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

La réutilisation du code est votre ami.

Tim Rogers
la source
1

vous pouvez utiliser

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

pour diviser la chaîne.

Haxer
la source
0

Tu ne peux pas le faire en ligne?

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

Sinon, si vous faites souvent cette opération exacte, vous pouvez toujours créer une constante ou quelque chose contenant ce tableau de caractères.

Comme d'autres l'ont noté, vous pouvez également, selon la documentation, utiliser nullou un tableau vide. Lorsque vous faites cela, il utilise automatiquement les espaces.

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

Si la répétition du même code est le problème, écrivez une méthode d'extension sur la classe String qui encapsule la logique de fractionnement.

Xhalent
la source
1
Cela ne répond pas vraiment à la question, désolé.
p.campbell
p. campbell: Oui, c'est le cas: OP a demandé une solution qui ne nécessite pas de copier le tableau de caractères partout. Une solution évidente consiste à créer une fonction pour effectuer la tâche. Cette réponse souligne qu'une telle fonction pourrait être une méthode d'extension. (La réponse pourrait être améliorée, en montrant le code pour le faire ...)
ToolmakerSteve