¿Cómo puedo eliminar todos los caracteres excepto los números de la cadena?
¿Cómo puedo eliminar todos los caracteres excepto los números de la cadena?
Respuestas:
En Python 2. *, con mucho, el enfoque más rápido es el .translatemétodo:
>>> x='aaa12333bb445bb54b5b52'
>>> import string
>>> all=string.maketrans('','')
>>> nodigs=all.translate(all, string.digits)
>>> x.translate(all, nodigs)
'1233344554552'
>>>
string.maketranscrea una tabla de traducción (una cadena de longitud 256) que en este caso es la misma que ''.join(chr(x) for x in range(256))(simplemente más rápida de hacer ;-). .translateaplica la tabla de traducción (que aquí es irrelevante ya queall esencialmente significa identidad) Y elimina los caracteres presentes en el segundo argumento, la parte clave.
.translatefunciona de manera muy diferente en cadenas Unicode (y cadenas en Python 3 - lo hago preguntas deseos especifican los cuales importante de liberación de Python es de interés!) - no es este sencillo, no es tan rápido, aunque todavía bastante usable.
Volviendo a 2. *, la diferencia de rendimiento es impresionante ...:
$ python -mtimeit -s'import string; all=string.maketrans("", ""); nodig=all.translate(all, string.digits); x="aaa12333bb445bb54b5b52"' 'x.translate(all, nodig)'
1000000 loops, best of 3: 1.04 usec per loop
$ python -mtimeit -s'import re; x="aaa12333bb445bb54b5b52"' 're.sub(r"\D", "", x)'
100000 loops, best of 3: 7.9 usec per loop
Acelerar las cosas entre 7 y 8 veces no es nada fácil, por lo translateque vale la pena conocer y utilizar el método. El otro enfoque popular no RE ...:
$ python -mtimeit -s'x="aaa12333bb445bb54b5b52"' '"".join(i for i in x if i.isdigit())'
100000 loops, best of 3: 11.5 usec per loop
es 50% más lento que RE, por lo que el .translateenfoque lo supera en un orden de magnitud.
En Python 3, o para Unicode, debe pasar .translateuna asignación (con ordinales, no caracteres directamente, como teclas) que devuelve Nonelo que desea eliminar. Aquí hay una manera conveniente de expresar esto para eliminar "todo menos" algunos caracteres:
import string
class Del:
def __init__(self, keep=string.digits):
self.comp = dict((ord(c),c) for c in keep)
def __getitem__(self, k):
return self.comp.get(k)
DD = Del()
x='aaa12333bb445bb54b5b52'
x.translate(DD)
También emite '1233344554552'. Sin embargo, poniendo esto en xx.py tenemos ...:
$ python3.1 -mtimeit -s'import re; x="aaa12333bb445bb54b5b52"' 're.sub(r"\D", "", x)'
100000 loops, best of 3: 8.43 usec per loop
$ python3.1 -mtimeit -s'import xx; x="aaa12333bb445bb54b5b52"' 'x.translate(xx.DD)'
10000 loops, best of 3: 24.3 usec per loop
... que muestra que la ventaja de rendimiento desaparece, para este tipo de tareas de "eliminación", y se convierte en una disminución del rendimiento.
x.translate(None, string.digits)en realidad da como resultado 'aaabbbbbb', que es lo contrario de lo que se pretende.
allconstrucción ... no estoy seguro de eso!
Uso re.sub, así:
>>> import re
>>> re.sub('\D', '', 'aas30dsa20')
'3020'
\D coincide con cualquier carácter que no sea un dígito, por lo tanto, el código anterior reemplaza esencialmente cada carácter que no sea un dígito para la cadena vacía.
O puede usar filter, así (en Python 2):
>>> filter(str.isdigit, 'aas30dsa20')
'3020'
Dado que en Python 3, filterdevuelve un iterador en lugar de a list, puede usar lo siguiente en su lugar:
>>> ''.join(filter(str.isdigit, 'aas30dsa20'))
'3020'
isdigit, generador con isdigtestá a medio camino entre ellos
rpara cadena cruda:re.sub(r"\D+", "", "aas30dsa20")
Puedes usar filter:
filter(lambda x: x.isdigit(), "dasdasd2313dsa")
En python3.0 tienes que unirte a esto (un poco feo :()
''.join(filter(lambda x: x.isdigit(), "dasdasd2313dsa"))
strpara listasegurarse de que funciona tanto en py2 como en py3:''.join(filter(lambda x: x.isdigit(), list("dasdasd2313dsa")))
en la línea de la respuesta de bayer:
''.join(i for i in s if i.isdigit())
-no es un dígito.
x.translate(None, string.digits)
eliminará todos los dígitos de la cadena. Para eliminar letras y conservar los dígitos, haga esto:
x.translate(None, string.letters)
TypeError: translate () toma exactamente un argumento (2 dados). Por qué esta pregunta fue votada en su estado actual es bastante frustrante.
La opción menciona en los comentarios que quiere mantener el lugar decimal. Esto se puede hacer con el método re.sub (según el segundo y la mejor respuesta de la OMI) enumerando explícitamente los caracteres para mantener, por ejemplo
>>> re.sub("[^0123456789\.]","","poo123.4and5fish")
'123.45'
Una versión rápida para Python 3:
# xx3.py
from collections import defaultdict
import string
_NoneType = type(None)
def keeper(keep):
table = defaultdict(_NoneType)
table.update({ord(c): c for c in keep})
return table
digit_keeper = keeper(string.digits)
Aquí hay una comparación de rendimiento vs. regex:
$ python3.3 -mtimeit -s'import xx3; x="aaa12333bb445bb54b5b52"' 'x.translate(xx3.digit_keeper)'
1000000 loops, best of 3: 1.02 usec per loop
$ python3.3 -mtimeit -s'import re; r = re.compile(r"\D"); x="aaa12333bb445bb54b5b52"' 'r.sub("", x)'
100000 loops, best of 3: 3.43 usec per loop
Entonces, es un poco más de 3 veces más rápido que la expresión regular, para mí. También es más rápido que el class Delanterior, porque defaultdictrealiza todas sus búsquedas en C, en lugar de Python (lento). Aquí está esa versión en mi mismo sistema, para comparar.
$ python3.3 -mtimeit -s'import xx; x="aaa12333bb445bb54b5b52"' 'x.translate(xx.DD)'
100000 loops, best of 3: 13.6 usec per loop
Feo pero funciona:
>>> s
'aaa12333bb445bb54b5b52'
>>> a = ''.join(filter(lambda x : x.isdigit(), s))
>>> a
'1233344554552'
>>>
list(s)?
filter(lambda x: x.isdigit(), s)funcionó bien para mí ... oh, es porque estoy usando Python 2.7.
$ python -mtimeit -s'import re; x="aaa12333bb445bb54b5b52"' 're.sub(r"\D", "", x)'
100000 bucles, lo mejor de 3: 2,48 usec por bucle
$ python -mtimeit -s'import re; x="aaa12333bab445bb54b5b52"' '"".join(re.findall("[a-z]+",x))'
100000 bucles, lo mejor de 3: 2.02 usec por bucle
$ python -mtimeit -s'import re; x="aaa12333bb445bb54b5b52"' 're.sub(r"\D", "", x)'
100000 bucles, lo mejor de 3: 2.37 usec por bucle
$ python -mtimeit -s'import re; x="aaa12333bab445bb54b5b52"' '"".join(re.findall("[a-z]+",x))'
100000 bucles, lo mejor de 3: 1.97 usec por bucle
Había observado que join es más rápido que sub.
Puedes leer cada personaje. Si es un dígito, inclúyalo en la respuesta. El str.isdigit() método es una forma de saber si un personaje es un dígito.
your_input = '12kjkh2nnk34l34'
your_output = ''.join(c for c in your_input if c.isdigit())
print(your_output) # '1223434'
Yo usé esto 'letters'debe contener todas las letras de las que desea deshacerse:
Output = Input.translate({ord(i): None for i in 'letters'}))
Ejemplo:
Input = "I would like 20 dollars for that suit"
Output = Input.translate({ord(i): None for i in 'abcdefghijklmnopqrstuvwxzy'}))
print(Output)
Salida:
20