Android / Java Regex para eliminar ceros adicionales de sub-cadenas

Tengo la siguiente cadena como entrada:

"2.0,3.00,-4.0,0.00,-0.00,0.03,2.01,0.001,-0.03,101" 

El resultado final será como:

 "2,3,-4,0,0,.03,2.01,.001,-.03,101" 

Es decir, todos los ceros iniciales y finales se eliminarán y los ceros positivos / negativos serán simplemente cero.

Podemos lograr esto dividiendo la cadena primero y usando Regex para cada parte. Pero mi tamaño de cadena es de más de 10000 .
¿Cómo podemos lograr esto usando Regex ?

Editar:

Análisis de las respuestas:

He probado todas las respuestas con Cadena "0.00,-0.00,00.00,-00.00,40.00,-40.00,4.0,-4.0,4.01,-4.01,04.01,-04.01,004.04,-004.04,0004.040,-0004.040,101,.40,-.40,0.40,-0.40" y la respuesta de Wiktor Stribiżew pasó todos los casos de prueba. (Ver aquí: https://regex101.com/r/tS8hE3/9 ) Otras respuestas fueron pasadas en la mayoría de los casos pero no todos.

Actualización del caso de prueba

Utilice el siguiente regex:

 String rx = "-?0+\\.(0)+\\b|\\.0+\\b|\\b0+(?=\\.\\d*[1-9])|\\b0+(?=[1-9]\\d*\\.)|(\\.\\d*?)0+\\b"; 

Y reemplazar con $1$2 . Ver otra demostración .

El regex coincide con varias alternativas y captura algunas partes de la cadena para luego volver a insertar durante el reemplazo:

  • -?0+\.(0)+\b – coincidente con un opcional - seguido con uno o más 0 s seguido con a . Y luego captura exactamente un 0 pero coincide con una o más ocurrencias (porque el (...) se coloca en el 0 y el + se aplica a este grupo); El límite de palabra al final requiere un carácter no-palabra para aparecer después de la última coincidente 0 . En el reemplazo, restauramos el 0 con backreference de $1 . Así, -00.00 o 00.00 será reemplazado por 0 .
  • | – o …
  • \.0+\b – un punto seguido de uno o más ceros antes de a , (ya que la cadena está delimitada por comas).
  • | – o …
  • \b0+(?=\.\d*[1-9]) – un límite de palabra (comienzo de cadena o una ubicación después , ) seguido de uno o más 0 s que son seguidos por . + Cero o más dígitos seguido de un dígito no 0 (por lo que eliminamos los ceros a la izquierda en la parte entera que sólo consiste en ceros)
  • | – o …
  • \b0+(?=[1-9]\d*\.) – un límite de palabra seguido de uno o más ceros seguido de un dígito no 0 antes de a . (Así, eliminamos todos los ceros iniciales de la parte entera que no es igual a 0 ).
  • | – o …
  • (\.\d*?)0+\b – capturar a . + Cero o más dígitos, pero tan pocos como sea posible, hasta el primer 0 , y luego sólo coincide con uno o más ceros (hasta el final de la cadena o , ) (así, nos deshacemos de los ceros finales en la parte decimal)

Respuesta antes de la actualización de los casos de prueba

Sugiero una regex muy simple y corta que hace lo que usted necesita:

 -0+\.(0)+\b|\.0+\b|\b0+(?=\.\d*[1-9]) 

Reemplazar con $1 .

Vea la demo de regex . Breve IDEONE demo :

 String re = "-0+\\.(0)+\\b|\\.0+\\b|\\b0+(?=\\.\\d*[1-9])"; String str = "2.0,3.00,-4.0,0.00,-0.00,0.03,2.01,0.001,-0.03,101,0.001,-0.03"; String expected = "2,3,-4,0,0,.03,2.01,.001,-.03,101,.001,-.03"; System.out.println(str.replaceAll(re, "$1").equals(expected)); // TRUE 

Explicación :

  • -0+\.(0)+\b – un menos seguido de uno o más 0 s ( 0+ ) seguido de un punto literal ( \. ) Seguido de uno o más ceros (y capturando sólo el último 0 coincidente con (0)+ ) seguido de un límite de palabras (ubicación anterior , en este contexto)
  • | – o …
  • \.0+\b – un punto literal ( \. ) Seguido de uno o más ceros seguidos con un límite de palabra (lugar antes , en este contexto)
  • | – o …
  • \b0+(?=\.\d*[1-9]) – un límite de palabra (lugar después , en este contexto) seguido de uno o más ceros que deben seguirse con un punto literal ( \. ), Luego cero o Más dígitos y luego un dígito de 1 a 9 rango (de modo que la parte decimal es más de 0 ).
 \.0+$|^(-)?0+(?=\.) 

Usted puede intentar esto. Substituya por $1 .if u consiga la cadena vacía o - después del reemplazo substituya por 0 Vea la demostración.

https://regex101.com/r/cZ0sD2/7

Si desea hacer el uso de cadena completa

 -?0*\.0+\b|\.0+(?=,|$)|(?:^|(?<=,))(-)?0+(?=\.) 

Ver demostración.

https://regex101.com/r/cZ0sD2/16

UPDATE para cubrir más casos como 01. , .100 , 01.10

 (?<=,|^)(?:[0.+-]+(?=0(?:,|\.\B|$))|0+(?=[1-9]))|\.0+\b|\b0+(?=\d*\.\b)|\.\B|(?<=[1-9])0+(?=,|$) 

Este patrón requiere más backtracking, así puede conseguir más lento en entrada grande. Cadena de Java:

 "(?<=,|^)(?:[0.+-]+(?=0(?:,|\\.\\B|$))|0+(?=[1-9]))|\\.0+\\b|\\b0+(?=\\d*\\.\\b)|\\.\\B|(?<=[1-9])0+(?=,|$)" 

Además del patrón anterior este partido

  • (?<=,|^)(?:|0+(?=[1-9])) agrega ceros a la izquierda precedentes [1-9]
  • \.0+\b modificado para coincidir con el período con ceros sólo antes de un límite de palabra
  • \b0+(?=\d*\.\b) coinciden con ceros en el límite si el periodo precedido por los dígitos opcionales a continuación
  • \.\B coincide con un período que bordea un límite no de palabras (por ejemplo ., )
  • (?<=[1-9])0+(?=,|$) Coincide con los ceros finales siguientes [1-9]

Demostración en regex101 o Regexplanet (haga clic en Java)


Respuesta antes de la actualización
También puede probar replaceAll esta regex con vacío.

 (?<=,|^)[0.+-]+(?=0(?:,|$))|\.0+\b|\b0+(?=\.) 
  • (?<=,|^)[0.+-]+(?=0(?:,|$)) Coincide con todas las partes que consisten solamente en [0.+-] con al menos un cero final. Limitada por el uso de aseveraciones de lookaround : (?<=,|^) Y (?=0(?:,|$))

  • |\.0+\b o coincide con un período seguido de uno o más ceros y un límite de palabra .

  • |\b0+(?=\.) O coincide con un límite seguido de uno o más ceros si hay un período por delante .

Los casos no cuestionados como 0. , 01 , 1.10 no están cubiertos por este patrón todavía. Como cadena de Java:

 "(?<=,|^)[0.+-]+(?=0(?:,|$))|\\.0+\\b|\\b0+(?=\\.)" 

Demostración en regex101 o Regexplanet (haga clic en Java)

Utilizando la lista de números de su pregunta, y algunos adicionales, el reemplazo de regex siguiente eliminará todos los ceros inicial y posterior.

 numbers.replaceAll("\\b0*([1-9]*[0-9]+)(\\.[0-9]*[1-9])?\\.?0*\\b", "$1$2"); 

Con entrada:

2,0,3,00, -4,0,0,00, -0,00,0.03,2.01,0.001, -0,03,101,101.1010,0020.00

el resultado es:

2,3, -4,0, -0,0,03,2,01,0,001, -0,03,101,101.101,20

Si desea tener decimales sin el 0 inicial, puede utilizar lo siguiente.

 numbers.replaceAll("\\b0*([0-9]+)(\\.[0-9]*[1-9])?\\.?0+\\b|0+(\\.[0-9]+?)0*\\b", "$1$2$3"); 

Con entrada:

2,0,3,00, -4,0,0,00, -0,00,0.03,2.01,0.001, -0,03,101,101.1010,0020.00

el resultado es:

2,3, -4,0, -0, 0,03,2,01, 0,001, – .03,101,101.101,20

Usted puede hacerlo con 2 veces el reemplazo:

Primero use \.0+(?=(,|$)) Y reemplace con ""

Entonces utilice (?!(^|,))-0(?=(,|$)) Y reemplácelo por "0"

¿Es posible utilizar sólo reemplazar? ejemplo:

 str.replaceAll("\.0+,|,0+(?=\.)", ","); 

manifestación

/(?!-)(?!0)[1-9][0-9]*\.?[0-9]*[1-9](?!0)|(?!-)(?!0)\.?[0-9]*[1-9](?!0)/g

  • Caracteres especiales de Android Sqlite
  • ¿Cómo busco una lista de correo electrónico para un formato determinado?
  • RegEx para encontrar URL en HTML tarda 25 segundos en Java / Android
  • Cómo analizar valores float de cadena utilizando REGEX en java
  • Matcher.replaceAll () y String.replaceAll () no parecen funcionar en Galaxy S 6
  • Expresión regular para eliminar todos los caracteres no imprimibles
  • ¿Qué significa * + en regexp
  • ¿Cómo lograr límite de palabras en Sqlite Android?
  • Utilizar un signo de interrogación como String en android
  • Cómo utilizar SpannableString con Regex en android?
  • Android / Java: comprueba si url es url válida de youtube
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.