La mejor manera de especificar espacios en blanco en una operación String.Split

243

Estoy dividiendo una cadena basada en espacios en blanco de la siguiente manera:

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

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

Es molesto definir la matriz char [] en todas partes de mi código. Quiero hacer esto. ¿Hay alguna forma más eficiente que no requiera la creación de la matriz de caracteres (que es propensa a errores si se copia en diferentes lugares)?

John Saunders
fuente
1
hace esto: myStr.Split (''); ¿no trabajo?
woolagaroo
44
Si entiendo esto correctamente esto sólo buscar un espacio, no genérica espacios en blanco
Vea también posibles duplicados, pero estas respuestas posteriores tienen SplitStringOptions. stackoverflow.com/questions/1562981/…
goodeye

Respuestas:

469

Si solo llamas:

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

o:

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

entonces se supone que el espacio en blanco es el carácter de división. Desde la string.Split(char[])página de documentación del método .

Si el parámetro separador es nullo no contiene caracteres, se supone que los caracteres de espacio en blanco son los delimitadores. Los caracteres de espacio en blanco están definidos por el estándar Unicode y regresan truesi se pasan al Char.IsWhiteSpacemétodo.

¡Siempre, siempre, siempre lee la documentación!

jason
fuente
2
El problema con la división por espacios en blanco es que si tiene que volver a armarlo, no sabe qué carácter de espacio en blanco volver a colocar.
Ross Presser, el
19
(char[])nulles un poco mejor ya que evita crear un nuevo objeto. (No se puede usar nullcon ninguna de las optionssobrecargas).
Artfunkel
55
@RossPresser: Volver a armar una cadena es un problema completamente diferente, por lo que no diría que este es un problema aquí. Pero si todo lo que necesita hacer es volver a unir la cadena exactamente como estaba antes, entonces quizás sea mejor mantener el original.
stakx - ya no contribuye el
44
Pregunta estúpida, pero si la usa null, ¿aún necesita especificar StringSplitOption.RemoveEmptyEntrieso se ignoran por defecto?
yu_ominae
2
@RossPresser: Dado que String.Split no proporciona ningún mecanismo para realizar un seguimiento de los caracteres utilizados para dividir la cadena, su observación no es relevante: uno no puede lograr lo que busca con String.Split, por lo que requiere un Q&A diferente.
ToolmakerSteve
207

Sí, ¡se necesita una respuesta más aquí!

Todas las soluciones hasta ahora abordan el dominio bastante limitado de la entrada canónica , a saber: un solo carácter de espacio en blanco entre los elementos (aunque la punta del sombrero a @cherno por al menos mencionar el problema). Pero lo presento en todos los escenarios menos oscuros, dividiendo todos estos debería producir resultados idénticos:

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 (en cualquiera de los sabores que se muestran en las otras respuestas aquí) simplemente no funciona bien a menos que adjunte el RemoveEmptyEntries opción con cualquiera de estos:

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

Como revela la ilustración, omitir la opción produce cuatro resultados diferentes (etiquetados A, B, C y D) frente al resultado único de las cuatro entradas cuando se usa RemoveEmptyEntries :

String.Split vs Regex.Split

Por supuesto, si no te gusta usar opciones, solo usa la alternativa regex :-)

Regex.Split(myStr, @"\s+").Where(s => s != string.Empty)
Michael Sorens
fuente
44
Creo, @RossPresser, que eso está cubierto por mi calificador "en todos los escenarios menos los más oscuros" porque incluso cuando quisiera recombinar los elementos me costaría mucho tener un caso en el que me preocupo por múltiples espacios. Me gustaría una forma canónica, un espacio entre cada uno. Así que estoy respetuosamente en desacuerdo: sería "raramente incorrecto" en lugar de "generalmente incorrecto".
Michael Sorens
1
CapitalizeEveryWord("This is line one.\n \nThis is line three.")
Ross Presser
3
Si realmente crees que esto es oscuro, entonces supongo que tendremos que estar de acuerdo en no estar de acuerdo, pero si dejo esta función fuera de mi software, perdería mi trabajo. A los usuarios les gusta que su contenido se vea como ellos quieren.
Ross Presser
44
Esta debería ser una respuesta aceptada, ya que es mucho más completa.
Dennis
1
Me pregunto por qué agregaste .Where(s => s != string.Empty)a Regex. Como especifica \s+(cualquier número de espacios) no puede haber ningún elemento vacío en el medio.
Jack Miller
44

De acuerdo con la documentación :

Si el parámetro separador es nulo o no contiene caracteres, se supone que los caracteres de espacio en blanco son los delimitadores. Los caracteres de espacio en blanco están definidos por el estándar Unicode y devuelven verdadero si se pasan al método Char.IsWhiteSpace.

Así que solo llame myStr.Split();No hay necesidad de pasar nada porque el separador es una paramsmatriz.

ageektrapped
fuente
11

¿Por qué no usas ?:

string[] ssizes = myStr.Split(' ', '\t');
Renatas M.
fuente
2
No hay sobrecarga dividida que requiera dos caracteres.
takrl
1
@takrl: Mira aquí cadena pública [] Split (params char [] separator) .NET v2
Renatas M.
Sí, esto toma una matriz de caracteres. Su fragmento de código pasa dos caracteres individuales.
takrl
15
@takrl: ¿sabes qué palabra clave params es?
Renatas M.
Bastante genial, +1 por eso. Probablemente la persona que rechazó el voto tampoco lo sabía.
takrl
3

Tenga en cuenta que los espacios en blanco adyacentes NO se tratarán como un delimitador único, incluso cuando se use String.Split(null). Si alguno de sus tokens está separado con múltiples espacios o pestañas, obtendrá cadenas vacías devueltas en su matriz.

De la documentación:

Cada elemento del separador define un carácter delimitador separado. Si dos delimitadores son adyacentes, o se encuentra un delimitador al principio o al final de esta instancia, el elemento de matriz correspondiente contiene Empty.

Cherno
fuente
2

¡Así que no copie y pegue! Extraiga una función para dividirla y reutilícela.

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

La reutilización del código es tu amigo.

Tim Rogers
fuente
1

puedes usar

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

dividir la cuerda.

Haxer
fuente
0

¿No puedes hacerlo en línea?

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

De lo contrario, si hace esto exactamente con frecuencia, siempre podría crear una constante o algo que contenga esa matriz de caracteres.

Como otros han notado, de acuerdo con la documentación, también puede usar nulluna matriz vacía. Cuando lo haga, usará los espacios en blanco automáticamente.

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

Si el problema es repetir el mismo código, escriba un método de extensión en la clase String que encapsule la lógica de división.

Xhalent
fuente
1
Esto realmente no responde la pregunta, lo siento.
p.campbell
pags. campbell: Sí, sí: OP solicitó una solución que no requiera copiar la matriz de caracteres en todas partes. Una solución obvia es crear una función para hacer la tarea. Esta respuesta señala que dicha función podría ser un método de extensión. (La respuesta podría mejorarse mostrando el código para hacerlo ...)
ToolmakerSteve