Pregunta ¿Por qué "dividir" en una cadena vacía devuelve una matriz no vacía?


Dividir en una cadena vacía devuelve una matriz de tamaño 1:

scala> "".split(',')
res1: Array[String] = Array("")

Considere que esto devuelve una matriz vacía:

scala> ",,,,".split(',')
res2: Array[String] = Array()

Por favor explique :)


76
2018-02-11 00:50


origen


Respuestas:


Por la misma razón que

",test" split ','

y

",test," split ','

devolverá una matriz de tamaño 2. Todo antes de la primera coincidencia se devuelve como el primer elemento.


27
2018-02-11 01:52



Si divides una naranja cero veces, tienes exactamente una pieza: la naranja.


58
2018-02-11 04:27



Dividir una cadena vacía devuelve la cadena vacía como primer elemento. Si no se encuentra ningún delimitador en la cadena objetivo, obtendrá una matriz de tamaño 1 que retiene la cadena original, incluso si está vacía.


40
2018-02-11 00:55



Los métodos de división de Java y Scala operan en dos pasos como este:

  • Primero, divide la cadena por delimitador. La consecuencia natural es que si la cadena no contiene el delimitador, se devuelve una matriz singleton que contiene solo la cadena de entrada,
  • Segundo, eliminar todas las cadenas vacías más a la derecha. Esta es la razón ",,,".split(",") devuelve una matriz vacía.

De acuerdo con esto, el resultado de "".split(",") debería ser una matriz vacía debido al segundo paso, ¿verdad?

Debería. Desafortunadamente, este es un caso de esquina presentado artificialmente. Y eso es malo, pero al menos está documentado en java.util.regex.Pattern, si recuerda echar un vistazo a la documentación:

Para n == 0, el resultado es igual que n <0, excepto las cadenas vacías finales   no será devuelto (Tenga en cuenta que el caso donde la entrada es en sí misma   la cadena vacía es especial, como se describió anteriormente, y el parámetro de límite   no se aplica allí).

Solución 1: Pase siempre -1 como el segundo parámetro

Entonces, te aconsejo que siempre pases n == -1 como el segundo parámetro (esto omitirá el paso dos anterior), a menos que sepa específicamente lo que quiere lograr / está seguro de que la cadena vacía no es algo que su programa obtendría como entrada.

TL; DR: La división de la cadena vacía es una caja de esquina introducida artificialmente y la documentación le advierte al respecto. Siempre pase -1 como el segundo parámetro para evitar errores, a menos que tenga una buena razón.

Solución 2: utilizar la clase de divisor de guayaba

Si ya está usando Guava en su proyecto, puede probar Splitter (documentación) clase. Tiene una API muy rica y hace que tu código sea muy fácil de entender.

Splitter.on(".").split(".a.b.c.") // "", "a", "b", "c", ""
Splitter.on(",").omitEmptyStrings().split("a,,b,,c") // "a", "b", "c"
Splitter.on(CharMatcher.anyOf(",.")).split("a,b.c") // "a", "b", "c"
Splitter.onPattern("=>?").split("a=b=>c") // "a", "b", "c"
Splitter.on(",").limit(2).split("a,b,c") // "a", "b,c"

25
2018-06-13 18:13



"a".split(",") -> "a" por lo tanto "".split(",") -> ""


23
2018-04-15 11:06



En todos los lenguajes de programación, sé que una cadena en blanco sigue siendo una cadena válida. Por lo tanto, hacer una división utilizando cualquier delimitador siempre devolverá una única matriz de elementos donde ese elemento es la cadena en blanco. Si se tratara de una Cadena nula (no en blanco), eso sería un problema diferente.


4
2018-02-11 00:57



Esta split el comportamiento se hereda de Java, para bien o para mal ...
Scala no anula la definición de la String primitivo.

Tenga en cuenta que puede utilizar el limit argumento para modificar el comportamiento:

El parámetro de límite controla el número de veces que se aplica el patrón y, por lo tanto, afecta la longitud de la matriz resultante. Si el límite n es mayor que cero, entonces el patrón se aplicará a lo sumo n - 1 veces, la longitud de la matriz no será mayor que n, y la última entrada de la matriz contendrá todas las entradas más allá del último delimitador coincidente. Si n no es positivo, el patrón se aplicará tantas veces como sea posible y la matriz puede tener cualquier longitud. Si n es cero, el patrón se aplicará tantas veces como sea posible, la matriz puede tener cualquier longitud, y las cadenas vacías posteriores se descartarán.

es decir, puede configurar el limit=-1 para obtener el comportamiento de (¿todos?) otros idiomas:

@ ",a,,b,,".split(",")
res1: Array[String] = Array("", "a", "", "b")

@ ",a,,b,,".split(",", -1)  // limit=-1
res2: Array[String] = Array("", "a", "", "b", "", "")

Parece ser bien conocido que el comportamiento de Java es bastante confuso pero:

El comportamiento anterior se puede observar desde al menos Java 5 a Java 8.

Hubo un intento de cambiar el comportamiento para devolver una matriz vacía al dividir una cadena vacía en JDK-6559590. Sin embargo, pronto se revirtió en JDK-8028321 cuando causa regresión en varios lugares. El cambio nunca se convierte en la versión inicial de Java 8.

Nota: El método de división no estaba en Java desde el principio (es no en 1.0.2) pero en realidad está allí desde al menos 1,4 (por ejemplo, ver JSR51 circa 2002). Todavía estoy investigando ...

Lo que no está claro es por qué Java eligió esto en primer lugar (mi sospecha es que originalmente era un descuido / error en un "caso extremo"), pero ahora irrevocablemente se adaptó al lenguaje y así permanece.


1
2017-10-20 04:47