Cómo extraer un número flotante de una cadena

Tengo una serie de cadenas similares al Current Level: 13.4 db. y me gustaría extraer sólo el número de punto flotante. Digo flotante y no decimal ya que a veces es entero. ¿RegEx puede hacer esto o hay una mejor manera?

Si tu flotador siempre se expresa en notación decimal algo así como

 >>> import re >>> re.findall("\d+\.\d+", "Current Level: 13.4 db.") ['13.4'] 

puede ser suficiente

Una versión más robusta sería:

 >>> re.findall(r"[-+]?\d*\.\d+|\d+", "Current Level: -13.2 db or 14.2 or 3") ['-13.2', '14.2', '3'] 

Si desea validar la entrada del usuario, también puede verificar si hay un flotador si se le acerca directamente:

 user_input = "Current Level: 1e100 db" for token in user_input.split(): try: # if this succeeds, you have your (first) float print float(token), "is a float" except ValueError: print token, "is something else" # => Would print ... # # Current is something else # Level: is something else # 1e+100 is a float # db is something else 

Es posible que desee probar algo como esto que cubra todas las bases, incluido el no contar con espacios en blanco después del número:

 >>> import re >>> numeric_const_pattern = r""" ... [-+]? # optional sign ... (?: ... (?: \d* \. \d+ ) # .1 .12 .123 etc 9.1 etc 98.1 etc ... | ... (?: \d+ \.? ) # 1. 12. 123. etc 1 12 123 etc ... ) ... # followed by optional exponent part if desired ... (?: [Ee] [+-]? \d+ ) ? ... """ >>> rx = re.compile(numeric_const_pattern, re.VERBOSE) >>> rx.findall(".1 .12 9.1 98.1 1. 12. 1 12") ['.1', '.12', '9.1', '98.1', '1.', '12.', '1', '12'] >>> rx.findall("-1 +1 2e9 +2E+09 -2e-9") ['-1', '+1', '2e9', '+2E+09', '-2e-9'] >>> rx.findall("current level: -2.03e+99db") ['-2.03e+99'] >>> 

Para copiar y pegar fácilmente:

 numeric_const_pattern = '[-+]? (?: (?: \d* \. \d+ ) | (?: \d+ \.? ) )(?: [Ee] [+-]? \d+ ) ?' rx = re.compile(numeric_const_pattern, re.VERBOSE) rx.findall("Some example: Jr. it. was .23 between 2.3 and 42.31 seconds") 

Python docs tiene una respuesta que cubre +/- y notación de exponentes

 scanf() Token Regular Expression %e, %E, %f, %g [-+]?(\d+(\.\d*)?|\.\d+)([eE][-+]?\d+)? %i [-+]?(0[xX][\dA-Fa-f]+|0[0-7]*|\d+) 

Esta expresión regular no admite formatos internacionales donde se usa una coma como el carácter separador entre la parte entera y la parte fraccionaria (3,14159). En ese caso, reemplace todos \. con [.,] en la expresión regular de flotación anterior.

  Regular Expression International float [-+]?(\d+([.,]\d*)?|[.,]\d+)([eE][-+]?\d+)? 
 re.findall(r"[-+]?\d*\.\d+|\d+", "Current Level: -13.2 db or 14.2 or 3") 

como se describe arriba, funciona muy bien! Una sugerencia sin embargo:

 re.findall(r"[-+]?\d*\.\d+|[-+]?\d+", "Current Level: -13.2 db or 14.2 or 3 or -3") 

también devolverá valores int negativos (como -3 al final de esta cadena)

Puede usar la siguiente expresión regular para obtener valores enteros y flotantes de una cadena:

 re.findall(r'[\d\.\d]+', 'hello -34 42 +34.478m 88 cricket -44.3') ['34', '42', '34.478', '88', '44.3'] 

Gracias Rex

Creo que encontrarás cosas interesantes en la siguiente respuesta que hice para una pregunta similar anterior:

https://stackoverflow.com/q/5929469/551449

En esta respuesta, propuse un patrón que permite a una expresión regular captar cualquier tipo de número y, como no tengo nada más que agregar, creo que es bastante completo

Otro enfoque que puede ser más legible es la simple conversión de tipos. He agregado una función de reemplazo para cubrir los casos en que las personas pueden ingresar a decimales europeos:

 >>> for possibility in "Current Level: -13.2 db or 14,2 or 3".split(): ... try: ... str(float(possibility.replace(',', '.'))) ... except ValueError: ... pass '-13.2' '14.2' '3.0' 

Esto tiene desventajas también sin embargo. Si alguien escribe “1,000”, esto se convertirá en 1. Además, se supone que las personas ingresarán con espacios en blanco entre las palabras. Este no es el caso con otros idiomas, como el chino.