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


Esta pregunta ya tiene una respuesta aquí:

Tengo un número de cadenas similares a Current Level: 13.4 db. y me gustaría extraer solo el número de coma flotante. Digo flotante y no decimal ya que a veces es entero. Puede RegEx hacer esto o hay una mejor manera?

Author: martineau, 2011-01-16

7 answers

Si su 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 un flotador caminando directamente a él:

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
 134
Author: miku,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-12-06 01:51:47

Puede que quieras probar algo como esto que cubra todas las bases, incluyendo no depender de los 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")
 46
Author: John Machin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-22 17:40:32

Python docs tiene una respuesta que cubre+/ -, y la 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 carácter separador entre el todo y la parte fraccionaria (3,14159). En ese caso, sustitúyase todo \. por [.,] en la expresión regular flotante anterior.

                        Regular Expression
International float     [-+]?(\d+([.,]\d*)?|[.,]\d+)([eE][-+]?\d+)?
 18
Author: IceArdor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-18 19:03:06
re.findall(r"[-+]?\d*\.\d+|\d+", "Current Level: -13.2 db or 14.2 or 3")

Como se describió anteriormente, 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)

 5
Author: Martin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-11-25 10:24:12

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

 3
Author: user3613331,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-05-21 15:37:07

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

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

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

 2
Author: eyquem,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:10:00

Otro enfoque que puede ser más legible es la conversión simple de tipos. He agregado una función de reemplazo para cubrir las instancias donde las personas pueden ingresar 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 también tiene desventajas. Si alguien escribe "1,000", esto se convertirá en 1. Además, asume que las personas ingresarán con espacios en blanco entre las palabras. Este no es el caso de otros idiomas, como el chino.

 0
Author: Tim McNamara,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-01-16 02:40:40