Extraería todos los números contenidos en una cadena. ¿Cuál es el más adecuado para el propósito, las expresiones regulares o el isdigit()
método?
Ejemplo:
line = "hello 12 hi 89"
Resultado:
[12, 89]
Si solo desea extraer solo enteros positivos, intente lo siguiente:
>>> str = "h3110 23 cat 444.4 rabbit 11 2 dog"
>>> [int(s) for s in str.split() if s.isdigit()]
[23, 11, 2]
Yo diría que esto es mejor que el ejemplo de expresiones regulares por tres razones. Primero, no necesitas otro módulo; en segundo lugar, es más legible porque no necesita analizar el mini-lenguaje regex; y tercero, es más rápido (y, por lo tanto, probablemente más pitónico):
python -m timeit -s "str = 'h3110 23 cat 444.4 rabbit 11 2 dog' * 1000" "[s for s in str.split() if s.isdigit()]"
100 loops, best of 3: 2.84 msec per loop
python -m timeit -s "import re" "str = 'h3110 23 cat 444.4 rabbit 11 2 dog' * 1000" "re.findall('\\b\\d+\\b', str)"
100 loops, best of 3: 5.66 msec per loop
Esto no reconocerá flotantes, enteros negativos o enteros en formato hexadecimal. Si no puede aceptar estas limitaciones, la respuesta de Slim a continuación será suficiente.
re
. Es una herramienta general y poderosa (para que aprendas algo muy útil). La velocidad es algo irrelevante en el análisis de registros (después de todo no es un solucionador numérico intensivo), elre
módulo está en la biblioteca estándar de Python y no hace daño cargarlo.mumblejumble45mumblejumble
en las que sabía que solo había un número. La solución es simpleint(filter(str.isdigit, your_string))
.str
que luego anula elstr
objeto y el método en Python base. Esa no es una buena práctica, ya que podría necesitarla más adelante en el script.int(filter(...))
se elevaráTypeError: int() argument must be a string...
para Python 3.5, por lo que puede usar la versión actualizada:int(''.join(filter(str.isdigit, your_string)))
para extraer todos los dígitos a un entero.Yo usaría una expresión regular:
Esto también coincidiría con 42 de
bla42bla
. Si solo desea números delimitados por límites de palabras (espacio, punto, coma), puede usar \ b:Para terminar con una lista de números en lugar de una lista de cadenas:
fuente
int
sobre él y listo. +1 especialmente para la última parte. Sinr'\b\d+\b' == '\\b\\d+\\b'
embargo, sugeriría cadenas sin formato ( ).int_list = [int(s) for s in re.findall('\\d+', 'hello 12 hi 89')]
map
.Esto es más que un poco tarde, pero también puede extender la expresión regex para tener en cuenta la notación científica.
Da todo bien!
Además, puede ver la expresión regular incorporada de AWS Glue
fuente
s = "4"
no devuelve coincidencias. ¿Se puede editar para que también se encargue de esto?[+-]?\d*[\.]?\d*(?:(?:[eE])[+-]?\d+)?
Este grupo da algunos falsos positivos (+
es decir , a veces se captura solo), pero puede manejar más formas, como.001
, además, no combina números automáticamente (como ens=2+1
)[-+]?[.]?[\d]+(?:,\d\d\d)*[\.]?\d*(?:[eE][-+]?\d+)?
, tan tonto de mi parte ... ¿cómo podría no pensar en eso?Supongo que quieres flotadores no solo enteros, así que haría algo como esto:
Tenga en cuenta que algunas de las otras soluciones publicadas aquí no funcionan con números negativos:
fuente
float
aint
.re.findall("[-\d]+", "1 -2")
continue
lugar depass
en el bucle?Si sabe que solo habrá un número en la cadena, es decir, 'hola 12 hola', puede intentar filtrar.
Por ejemplo:
Pero ten cuidado! :
fuente
TypeError: int() argument must be a string, a bytes-like object or a number, not 'filter'
- fijándolo mediante el usoint("".join(filter(str.isdigit, '200 grams')))
fuente
Estaba buscando una solución para eliminar las máscaras de cadenas, específicamente de los números de teléfono brasileños, esta publicación no respondió pero me inspiró. Esta es mi solución:
fuente
Usar Regex a continuación es la forma
con findall
re.findall(r'\d+', "hello 12 hi 89")
re.findall(r'\b\d+\b', "hello 12 hi 89 33F AC 777")
fuente
findall()
repl_str = re.compile('\d+.?\d*')
debería ser:repl_str = re.compile('\d+\.?\d*')
Para un ejemplo reproducible usando python3.7re.search(re.compile(r'\d+.?\d*'), "42G").group()
'42G're.search(re.compile(r'\d+\.?\d*'), "42G").group()
'42'Hola ,
Puede buscar todos los enteros en la cadena a través del dígito utilizando la expresión Findall.
En el segundo paso, cree una lista res2 y agregue los dígitos encontrados en la cadena a esta lista
espero que esto ayude
Saludos, Diwakar Sharma
fuente
Esta respuesta también contiene el caso cuando el número es flotante en la cadena
fuente
Me sorprende ver que nadie ha mencionado aún el uso de
itertools.groupby
una alternativa para lograr esto.Puede usar
itertools.groupby()
junto constr.isdigit()
para extraer números de la cadena como:El valor retenido
l
será:PD: Esto es solo con fines ilustrativos para mostrar que, como alternativa, también podríamos usar
groupby
para lograr esto. Pero esta no es una solución recomendada. Si desea lograr esto, debe usar la respuesta aceptada de fmark basada en la comprensión de la lista con unstr.isdigit
filtro.fuente
Solo estoy agregando esta respuesta porque nadie agregó una usando el manejo de excepciones y porque esto también funciona para flotantes
Salida:
fuente
Para atrapar diferentes patrones, es útil consultar con diferentes patrones.
Configure todos los patrones que capturan diferentes patrones de números de interés:
(encuentra comas) 12,300 o 12,300.00
'[\ d] + [., \ d] +'
(encuentra flotantes) 0.123 o .123
'[\ d] * [.] [\ d] +'
(encuentra números enteros) 123
'[\ d] +'
Combine con tubería (|) en un patrón con múltiples o condicionales .
(Nota: Ponga patrones complejos primero; de lo contrario, los patrones simples devolverán fragmentos de la captura compleja en lugar de que la captura compleja devuelva la captura completa).
A continuación, confirmaremos que hay un patrón presente
re.search()
y luego devolveremos una lista iterable de capturas. Finalmente, imprimiremos cada captura utilizando la notación de paréntesis para subseleccionar el valor de retorno del objeto coincidente del objeto coincidente.Devoluciones:
fuente
Como ninguno de estos se refería a números financieros del mundo real en documentos de Excel y Word que necesitaba encontrar, aquí está mi variación. Maneja ints, flotantes, números negativos, números de moneda (porque no responde en división), y tiene la opción de soltar la parte decimal y solo devolver ints, o devolver todo.
También maneja el sistema de números de Indian Laks donde las comas aparecen de manera irregular, no cada 3 números separados.
No maneja la notación científica o los números negativos entre paréntesis en los presupuestos, parecerán positivos.
Tampoco extrae fechas. Hay mejores formas de encontrar fechas en cadenas.
fuente
@jmnas, me gustó tu respuesta, pero no encontró flotadores. Estoy trabajando en un script para analizar el código que va a un molino CNC y necesitaba encontrar las dimensiones X e Y que pueden ser enteros o flotantes, por lo que adapté su código a lo siguiente. Esto encuentra int, float con valores positivos y negativos. Todavía no encuentra valores con formato hexadecimal, pero podría agregar "x" y "A" a través de "F" a la
num_char
tupla y creo que analizaría cosas como '0x23AC'.fuente
La mejor opción que encontré está debajo. Extraerá un número y puede eliminar cualquier tipo de carbón.
fuente
Para los números de teléfono, simplemente puede excluir todos los caracteres que no sean dígitos con \ D en regex:
fuente