Il modo migliore per specificare gli spazi bianchi in un'operazione String.Split


243

Sto dividendo una stringa in base agli spazi bianchi come segue:

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

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

È fastidioso definire l'array char [] ovunque nel mio codice. Voglio farlo. Esiste un modo più efficace che non richiede la creazione dell'array di caratteri (che è soggetto a errori se copiato in luoghi diversi)?


1
fa questo: myStr.Split (''); non funziona?
Woolagaroo,

4
Se lo capisco correttamente,

Vedi anche possibili duplicati, ma queste risposte successive hanno SplitStringOptions. stackoverflow.com/questions/1562981/...
goodeye

Risposte:


469

Se chiami semplicemente:

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

o:

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

quindi si presume che lo spazio bianco sia il carattere di divisione. Dalla string.Split(char[])pagina di documentazione del metodo .

Se il parametro separator è nullo non contiene caratteri, si presume che i caratteri spazi siano i delimitatori. I caratteri dello spazio bianco sono definiti dallo standard Unicode e restituiscono truese vengono passati al Char.IsWhiteSpacemetodo.

Leggi sempre, sempre, sempre la documentazione!


2
Il problema con la divisione per spazio bianco è che se devi rimetterlo insieme, non sai quale personaggio di spazio bianco rimettere.
Ross Presser,

19
(char[])nullè leggermente migliore in quanto evita di creare un nuovo oggetto. (Non è possibile utilizzare nullcon nessuno dei optionssovraccarichi).
Artfunkel,

5
@RossPresser: ricomporre una stringa è un problema completamente diverso, quindi non direi che questo è un problema qui. Ma se tutto ciò che devi fare è rimettere la stringa esattamente come prima, allora forse meglio mantenere l'originale.
stakx - non contribuisce più il

4
Domanda stupida, ma se lo usi null, devi ancora specificare StringSplitOption.RemoveEmptyEntrieso vengono ignorati per impostazione predefinita?
yu_ominae,

2
@RossPresser: Poiché String.Split non fornisce alcun meccanismo per tenere traccia dei caratteri utilizzati per dividere la stringa, la tua osservazione non è rilevante: non è possibile ottenere ciò che cerchi utilizzando String.Split, quindi è necessario un diverso Q&A.
ToolmakerSteve

207

Sì, c'è bisogno di un'altra risposta qui!

Tutte le soluzioni finora affrontano il dominio piuttosto limitato dell'input canonico , vale a dire: un singolo carattere di spazio bianco tra gli elementi (anche se punta del cappello a @cherno per almeno menzionare il problema). Ma sostengo che in tutti gli scenari tranne quelli più oscuri, suddividere tutti questi dovrebbe produrre risultati identici:

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 uno dei gusti mostrati nelle altre risposte qui) semplicemente non funziona bene a meno che non si colleghi l' RemoveEmptyEntriesopzione con uno di questi:

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

Come mostra l'illustrazione, omettendo l'opzione si ottengono quattro risultati diversi (etichettati A, B, C e D) rispetto al risultato singolo di tutti e quattro gli input quando si utilizza RemoveEmptyEntries:

String.Split vs Regex.Split

Naturalmente, se non ti piace usare le opzioni, usa l'alternativa regex :-)

Regex.Split(myStr, @"\s+").Where(s => s != string.Empty)

4
Penso, @RossPresser, che questo sia coperto dal mio qualificatore "in tutti gli scenari tranne quelli più oscuri" perché anche quando volevo ricombinare gli elementi mi sarebbe difficile trovare un caso in cui mi occupo di più spazi. Vorrei una forma canonica - uno spazio tra ciascuno. Quindi non sono rispettosamente d'accordo - sarebbe "raramente sbagliato" piuttosto che "solitamente sbagliato".
Michael Sorens,

1
CapitalizeEveryWord("This is line one.\n \nThis is line three.")
Ross Presser,

3
Se pensi davvero che questo sia oscuro, allora suppongo che dovremo concordare di non essere d'accordo, ma se avessi lasciato questa funzione fuori dal mio software, avrei perso il lavoro. Agli utenti piace che il loro contenuto appaia come vogliono.
Ross Presser,

4
Questa dovrebbe essere una risposta accettata, poiché è molto più completa.
Dennis,

1
Mi chiedo perché hai aggiunto .Where(s => s != string.Empty)al Regex. Dato che si specifica \s+(qualsiasi numero di spazi) non ci può essere alcun elemento vuoto in mezzo.
Jack Miller,

44

Secondo il documentazione :

Se il parametro separator è null o non contiene caratteri, si presume che i caratteri spazi siano i delimitatori. I caratteri dello spazio bianco sono definiti dallo standard Unicode e restituiscono true se vengono passati al metodo Char.IsWhiteSpace.

Quindi basta chiamare myStr.Split();Non è necessario passare nulla perché il separatore è un paramsarray.


11

Perché non usi ?:

string[] ssizes = myStr.Split(' ', '\t');

2
Non esiste un sovraccarico Split che richiede due caratteri.
takrl,

1
@takrl: guarda qui stringa pubblica [] Split (params char [] separator) .NET v2
Renatas M.

Sì, questo richiede una matrice di caratteri. Lo snippet di codice passa due caratteri singoli.
takrl,

15
@takrl: sai qual è la parola chiave params ???
Renatas M.

Abbastanza bello, +1 per quello. Probabilmente neanche la persona che ha effettuato il downvoting.
takrl,

3

Si noti che gli spazi bianchi adiacenti NON saranno trattati come un unico delimitatore, anche durante l'utilizzo String.Split(null) . Se uno qualsiasi dei token è separato con più spazi o schede, verranno restituite stringhe vuote nell'array.

Dalla documentazione:

Ogni elemento del separatore definisce un carattere delimitatore separato. Se due delimitatori sono adiacenti o viene trovato un delimitatore all'inizio o alla fine di questa istanza, l'elemento della matrice corrispondente contiene Vuoto.


2

Quindi non copiare e incollare! Estrai una funzione per eseguire la divisione e riutilizzarla.

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

Il riutilizzo del codice è tuo amico.



1

Puoi usare

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

per dividere la stringa.


0

Non puoi farlo in linea?

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

Altrimenti, se fai spesso questa cosa esatta, potresti sempre creare una costante o qualcosa contenente quell'array di caratteri.

Come altri hanno notato, in base alla documentazione è possibile utilizzare anche nullun array vuoto. Quando lo fai, utilizzerà automaticamente gli spazi bianchi.

var sizes = subject.Split(null);

0

Se il problema è ripetere lo stesso codice, scrivere un metodo di estensione sulla classe String che incapsuli la logica di divisione.


1
Questo non risponde davvero alla domanda, scusa.
Campbell

p. campbell: Sì, lo fa: OP ha chiesto una soluzione che non richieda la copia dell'array di caratteri ovunque. Una soluzione ovvia è quella di creare una funzione per svolgere l'attività. Questa risposta sottolinea che tale funzione potrebbe essere un metodo di estensione. (La risposta potrebbe essere migliorata, mostrando il codice per farlo ...)
ToolmakerSteve

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.