2010-09-04 22 views
10

Necesito reemplazar caracteres no numéricos de una cadena.Reemplazar caracteres no numéricos

Por ejemplo, "8-4545-225-144" debe ser "84545225144"; "$ 334fdf890 == -" debe ser "334890".

¿Cómo puedo hacer esto?

Respuesta

17
''.join(c for c in S if c.isdigit()) 
+0

Odio cuando las personas cierran una lista de comprensión cuando la expresión de un generador es la opción correcta. Usted, señor, gana un internet (y un voto positivo). – delnan

+0

+1 para solución no regex. odio cuando las personas usan expresiones regulares para todo, algunos objetivos se adaptan mejor con la solución no regex – killown

+1

@killown: Personalmente encuentro la opción de expresiones regulares más legible. Tal vez es porque he trabajado tanto con expresiones regulares, pero mirando el código de @ KennyTM puedo ver de inmediato lo que hace; esto me lleva un segundo entender. –

17

Es posible con expresiones regulares.

import re 

... 

return re.sub(r'\D', '', theString) 
0

Aunque un poco más complicado de configurar, utilizando el método translate() cadena a eliminar los caracteres que se muestran a continuación pueden tanto como 4-6 veces más rápido que el uso de join() o re.sub() según la duración pruebas que realizamos - así que si es algo que se hace muchas veces, quizás quieras considerar usarlo.

nonnumerics = ''.join(c for c in ''.join(chr(i) for i in range(256)) if not c.isdigit()) 

astring = '123-$ab #6789' 
print astring.translate(None, nonnumerics) 
# 1236789 
+0

El método str.translate se prefiere sobre string.translate. –

+0

@Roger Pate, buen punto, los viejos hábitos son difíciles de romper ... He actualizado el código en mi respuesta en consecuencia.Gracias por señalarlo y permitirme mejorar el código de muestra. – martineau

0

prefiero expresiones regulares, así que aquí está una manera si se quiere

import re 
myStr = '$334fdf890==-' 
digts = re.sub('[^0-9]','',myStr) 

Esto debe reemplazar todas las ocurrencias no numéricos con '' es decir, sin nada. Tan variable digts debería ser el momento '334890'

1

Vamos a la join y las versiones re:

In [3]: import re 

In [4]: def withRe(theString): return re.sub('\D', '', theString) 
    ...: 

In [5]: 

In [6]: def withJoin(S): return ''.join(c for c in S if c.isdigit()) 
    ...: 


In [11]: s = "8-4545-225-144" 

In [12]: %timeit withJoin(s) 
100000 loops, best of 3: 6.89 us per loop 

In [13]: %timeit withRe(s) 
100000 loops, best of 3: 4.77 us per loop 

La versión join es mucho más agradable, en comparación con el re uno, pero por desgracia es un 50% más lento. Entonces, si el rendimiento es un problema, podría ser necesario sacrificar la elegancia.

EDITAR

In [16]: def withFilter(s): return filter(str.isdigit, s) 
    ....: 
In [19]: %timeit withFilter(s) 
100000 loops, best of 3: 2.75 us per loop 

Parece que filter es el ganador rendimiento y facilidad de lectura

3

filter(str.isdigit, s) es más rápido y la OMI más clara que cualquier otra cosa que aparece aquí.

También lanzará un TypeError si s es de tipo Unicode. Dependiendo de la definición de "dígitos" que desee, esto puede ser más o menos útil que la alternativa filter(type(s).isdigit, s), un poco más lenta pero aún más rápida que las versiones de re y comprensión para mí.

Editar: Aunque si usted es un lechón pobre pegado con Python 3, que tendrá que utilizar "".join(filter(str.isdigit, s)) que te pone firmemente en el ámbito de lo que es equivalente mal desempeño. Tal progreso.

Cuestiones relacionadas