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:
- División de la cadena con RegEx en Android
- Formato de registro de registro de Android c2dm
- Referencia a grupos coincidentes anteriores dentro de un regex
- Cómo encontrar elementos por subcadena de ID usando la sintaxis del selector Jsoup?
- Buscar una subcadena entre ciertos caracteres en un índice desconocido
"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.
- Manejo de spoiler BBcode Android
- Java Regex lookahead toma demasiado tiempo
- Jsoup obtiene elemento en value = ""
- Regex palabra entera
- Necesito una consulta SQL para encontrar todas las palabras que puede hacer con un conjunto de letras, incluyendo hasta dos fichas en blanco
- Identificar el tipo de patrón de regex
- Regex <img> Análisis de etiquetas con src, width, height
- Excluir etiquetas HTML y algunos caracteres UNICODE mientras busca en SQLite
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ás0
s seguido con a.
Y luego captura exactamente un0
pero coincide con una o más ocurrencias (porque el(...)
se coloca en el0
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 coincidente0
. En el reemplazo, restauramos el0
con backreference de$1
. Así,-00.00
o00.00
será reemplazado por0
. -
|
– 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ás0
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 a0
). -
|
– o … -
(\.\d*?)0+\b
– capturar a.
+ Cero o más dígitos, pero tan pocos como sea posible, hasta el primer0
, 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ás0
s (0+
) seguido de un punto literal (\.
) Seguido de uno o más ceros (y capturando sólo el último0
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 de0
).
\.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.
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