reemplazar - Eliminar caracteres específicos de una cadena en Python
quitar comas de un string python (25)
Estoy tratando de eliminar caracteres específicos de una cadena usando Python. Este es el código que estoy usando ahora. Lamentablemente parece que no hace nada a la cadena.
for char in line:
if char in " ?.!/;:":
line.replace(char,'''')
¿Cómo hago esto correctamente?
Fácil peasy con re.sub
en Python 3.5
re.sub(''/ |/?|/.|/!|//|/;|/:'', '''', line)
Ejemplo
>>> import re
>>> line = ''Q: Do I write ;/.??? No!!!''
>>> re.sub(''/ |/?|/.|/!|//|/;|/:'', '''', line)
''QDoIwriteNo''
Explicación
En expresiones regulares ( expresiones regulares ), |
es un espacio lógico OR y /
escapes y caracteres especiales que pueden ser comandos regex reales. sub
significa sustitución.
En Python 3.5
p.ej,
os.rename(file_name, file_name.translate({ord(c): None for c in ''0123456789''}))
Para eliminar todo el número de la cadena
Abajo uno ... sin usar el concepto de expresión regular ...
ipstring ="text with symbols!@#$^&*( ends here"
opstring=''''
for i in ipstring:
if i.isalnum()==1 or i=='' '':
opstring+=i
pass
print opstring
Aquí está mi versión compatible con Python 2/3. Desde la traducción de la API ha cambiado.
def remove(str_, chars):
"""Removes each char in `chars` from `str_`.
Args:
str_: String to remove characters from
chars: String of to-be removed characters
Returns:
A copy of str_ with `chars` removed
Example:
remove("What?!?: darn;", " ?.!:;") => ''Whatdarn''
"""
try:
# Python2.x
return str_.translate(None, chars)
except TypeError:
# Python 3.x
table = {ord(char): None for char in chars}
return str_.translate(table)
Aquí hay algunas formas posibles de lograr esta tarea:
def attempt1(string):
return "".join([v for v in string if v not in ("a", "e", "i", "o", "u")])
def attempt2(string):
for v in ("a", "e", "i", "o", "u"):
string = string.replace(v, "")
return string
def attempt3(string):
import re
for v in ("a", "e", "i", "o", "u"):
string = re.sub(v, "", string)
return string
def attempt4(string):
return string.replace("a", "").replace("e", "").replace("i", "").replace("o", "").replace("u", "")
for attempt in [attempt1, attempt2, attempt3, attempt4]:
print(attempt("murcielago"))
PD: En vez de usar "?.! / ;:", los ejemplos usan las vocales ... y sí, "murcielago" es la palabra en español para decir bat ... palabra graciosa ya que contiene todas las vocales :)
PS2: Si estás interesado en el rendimiento, puedes medir estos intentos con un código simple como:
import timeit
K = 1000000
for i in range(1,5):
t = timeit.Timer(
f"attempt{i}(''murcielago'')",
setup=f"from __main__ import attempt{i}"
).repeat(1, K)
print(f"attempt{i}",min(t))
En mi caja obtendrías:
attempt1 2.2334518376057244
attempt2 1.8806643818474513
attempt3 7.214925774955572
attempt4 1.7271184513757465
Así que parece que intent4 es el más rápido para esta entrada en particular.
División recursiva: s = cadena; caracteres = caracteres para eliminar
def strip(s,chars):
if len(s)==1:
return "" if s in chars else s
return strip(s[0:int(len(s)/2)],chars) + strip(s[int(len(s)/2):len(s)],chars)
ejemplo:
print(strip("Hello!","lo")) #He!
El que pregunta casi lo tiene. Como la mayoría de las cosas en Python, la respuesta es más simple de lo que piensas.
>>> line = "H E?.LL!/;O:: "
>>> for char in '' ?.!/;:'':
... line = line.replace(char,'''')
...
>>> print line
HELLO
No tiene que hacer lo anidado if / for loop, sino que DEBE verificar cada carácter individualmente.
Incluso el siguiente enfoque funciona
line = "a,b,c,d,e"
alpha = list(line)
while '','' in alpha:
alpha.remove('','')
finalString = ''''.join(alpha)
print(finalString)
salida >> abcde
Las cadenas en Python son inmutables (no se pueden cambiar). Debido a esto, el efecto de line.replace(...)
es simplemente crear una nueva cadena, en lugar de cambiar la antigua. Debe volver a vincularlo (asignarlo) a la line
para que la variable tome el nuevo valor, con esos caracteres eliminados.
Además, la forma en que lo está haciendo será relativamente lenta. También es probable que sea un poco confuso para los pitones experimentados, quienes verán una estructura doblemente anidada y pensarán por un momento que algo más complicado está sucediendo.
Comenzando en Python 2.6 y versiones más recientes de Python 2.x *, puedes usar str.translate
, (pero str.translate
leyendo para conocer las diferencias de Python 3):
line = line.translate(None, ''!@#$'')
o reemplazo de expresiones regulares con re.sub
import re
line = re.sub(''[!@#$]'', '''', line)
Los caracteres encerrados entre paréntesis constituyen una clase de caracteres . Todos los caracteres en line
que están en esa clase se reemplazan con el segundo parámetro a sub
: una cadena vacía.
En Python 3, las cadenas son Unicode. Tendrás que traducir un poco diferente. kevpie menciona esto en un comment en una de las respuestas, y está anotado en la str.translate .
Al llamar al método de translate
de una cadena Unicode, no puede pasar el segundo parámetro que usamos anteriormente. Tampoco puede pasar None
como el primer parámetro, o incluso una tabla de traducción de string.maketrans
. En su lugar, pasa un diccionario como único parámetro. Este diccionario asigna los valores ordinales de los caracteres (es decir, el resultado de llamarlos) a los valores ordinales de los caracteres que deben reemplazarlos, o, de manera útil para nosotros, None
para indicar que se deben eliminar.
Entonces, para hacer el baile anterior con una cadena de Unicode, llamarías algo así como
translation_table = dict.fromkeys(map(ord, ''!@#$''), None)
unicode_line = unicode_line.translate(translation_table)
Aquí, las dict.fromkeys
y el map
se utilizan para generar sucintamente un diccionario que contiene
{ord(''!''): None, ord(''@''): None, ...}
Aún más simple, como lo pone otra respuesta , cree el diccionario en su lugar:
unicode_line = unicode_line.translate({ord(c): None for c in ''!@#$''})
* por compatibilidad con Pythons anteriores, puede crear una tabla de traducción "nula" para pasarla en lugar de None
:
import string
line = line.translate(string.maketrans('''', ''''), ''!@#$'')
Aquí string.maketrans
se usa para crear una tabla de traducción , que es solo una cadena que contiene los caracteres con valores ordinales de 0 a 255.
Las cuerdas son inmutables en Python. El método de replace
devuelve una nueva cadena después del reemplazo. Tratar:
for char in line:
if char in " ?.!/;:":
line = line.replace(char,'''')
Me estoy perdiendo el punto aquí, o es solo lo siguiente:
>>> string = "ab1cd1ef"
>>> string.replace("1","")
''abcdef''
>>>
Ponlo en un bucle:
>>>
>>> a = "a!b@c#d$"
>>> b = "!@#$"
>>> for char in b:
... a = a.replace(char,"")
...
>>> print a
abcd
>>>
Me sorprendió que nadie hubiera recomendado usar la función de filtro integrado.
import operator
import string # only for the example you could use a custom string
s = "1212edjaq"
Digamos que queremos filtrar todo lo que no es un número. Usar el método incorporado del filtro "... es equivalente a la expresión del generador (elemento por elemento en iterable si función (elemento))" [ Built-in de Python 3: Filtro ]
sList = list(s)
intsList = list(string.digits)
obj = filter(lambda x: operator.contains(intsList, x), sList)))
En Python 3 esto vuelve.
>> <filter object @ hex>
Para obtener una cadena impresa,
nums = "".join(list(obj))
print(nums)
>> "1212"
No estoy seguro de cómo se clasifica el filtro en términos de eficiencia, pero es una buena cosa saber cómo usar cuando se hacen listas de comprensión y demás.
ACTUALIZAR
Lógicamente, dado que el filtro funciona, también podría usar la comprensión de listas y, por lo que he leído, se supone que es más eficiente porque las lambdas son los gestores de fondos de cobertura de Wall Street del mundo de la función de programación. Otra ventaja es que se trata de una sola línea que no requiere ninguna importación. Por ejemplo, usando la misma cadena ''s'' definida anteriormente,
num = "".join([i for i in s if i.isdigit()])
Eso es. El retorno será una cadena de todos los caracteres que son dígitos en la cadena original.
Si tiene una lista específica de caracteres aceptables / inaceptables, solo necesita ajustar la parte ''if'' de la lista de comprensión.
target_chars = "".join([i for i in s if i in some_list])
o alternativamente,
target_chars = "".join([i for i in s if i not in some_list])
Mi método que usaría probablemente no funcionaría tan eficientemente, pero es muy simple. Puedo eliminar varios caracteres en diferentes posiciones a la vez, utilizando el corte y el formato. Aquí hay un ejemplo:
words = "things"
removed = "%s%s" % (words[:3], words[-1:])
Esto resultará en ''eliminado'' sosteniendo la palabra ''esto''.
El formato puede ser muy útil para imprimir variables a mitad de camino a través de una cadena de impresión. Puede insertar cualquier tipo de datos usando un % seguido del tipo de datos de la variable; todos los tipos de datos pueden usar % s , y flotantes (también conocidos como decimales) y enteros pueden usar % d .
El corte se puede utilizar para el control complejo de cadenas. Cuando pongo palabras [: 3] , me permite seleccionar todos los caracteres de la cadena desde el principio (los dos puntos están antes del número, esto significará ''desde el principio hasta'') hasta el 4º carácter (incluye el 4º. personaje). La razón 3 es igual hasta que la 4ª posición es porque Python comienza en 0. Luego, cuando coloco la palabra [-1:] , significa que el segundo último carácter se encuentra al final (los dos puntos están detrás del número). Poner -1 hará que Python cuente desde el último carácter, en lugar del primero. Una vez más, Python comenzará a 0. Entonces, la palabra [-1:] básicamente significa ''desde el segundo último carácter hasta el final de la cadena.
Por lo tanto, al cortar los caracteres antes del carácter que quiero eliminar y los caracteres posteriores y unirlos, puedo eliminar el carácter no deseado. Piensa en ello como una salchicha. En el medio está sucio, así que quiero deshacerme de él. Simplemente corte los dos extremos que quiero y luego los junto sin la parte no deseada en el medio.
Si quiero eliminar varios caracteres consecutivos, simplemente cambio los números en el [] (parte de corte). O si quiero eliminar varios personajes de diferentes posiciones, simplemente puedo unir varias porciones a la vez.
Ejemplos:
words = "control"
removed = "%s%s" % (words[:2], words[-2:])
eliminado es igual a ''cool''.
words = "impacts"
removed = "%s%s%s" % (words[1], words[3:5], words[-1])
eliminado es igual a ''macs''.
En este caso, [3: 5] significa carácter en la posición 3 a través de carácter en la posición 5 (excluyendo el carácter en la posición final).
Recuerde, Python comienza a contar a 0 , por lo que también necesitará hacerlo.
Para el requisito inverso de solo permitir ciertos caracteres en una cadena, puede usar expresiones regulares con un operador de complemento establecido [^ABCabc]
. Por ejemplo, para eliminar todo excepto las letras ascii, los dígitos y el guión:
>>> import string
>>> import re
>>>
>>> phrase = '' There were "nine" (9) chick-peas in my pocket!!! ''
>>> allow = string.letters + string.digits + ''-''
>>> re.sub(''[^%s]'' % allow, '''', phrase)
''Therewerenine9chick-peasinmypocket''
De la documentación de la expresión regular de python :
Los caracteres que no están dentro de un rango pueden combinarse complementando el conjunto. Si el primer carácter del conjunto es
''^''
, todos los caracteres que no estén en el conjunto coincidirán. Por ejemplo,[^5]
coincidirá con cualquier carácter excepto ''5'', y[^^]
coincidirá con cualquier carácter excepto''^''
.^
no tiene un significado especial si no es el primer carácter del conjunto.
Prueba este:
def rm_char(original_str, need2rm):
'''''' Remove charecters in "need2rm" from "original_str" ''''''
return original_str.translate(str.maketrans('''','''',need2rm))
Este método funciona bien en Python 3.5.2
Qué tal esto:
def text_cleanup(text):
new = ""
for i in text:
if i not in " ?.!/;:":
new += i
return new
También puede usar una función para sustituir diferentes tipos de expresiones regulares u otros patrones con el uso de una lista. Con eso, puedes mezclar expresiones regulares, clases de caracteres y un patrón de texto realmente básico. Es realmente útil cuando necesitas sustituir muchos elementos como HTML.
* NB: trabaja con Python 3.x
import re # Regular expression library
def string_cleanup(x, notwanted):
for item in notwanted:
x = re.sub(item, '''', x)
return x
line = "<title>My example: <strong>A text %very% $clean!!</strong></title>"
print("Uncleaned: ", line)
# Get rid of html elements
html_elements = ["<title>", "</title>", "<strong>", "</strong>"]
line = string_cleanup(line, html_elements)
print("1st clean: ", line)
# Get rid of special characters
special_chars = ["[!@#$]", "%"]
line = string_cleanup(line, special_chars)
print("2nd clean: ", line)
En la función string_cleanup, toma su cadena xy su lista no deseada como argumentos. Para cada elemento en esa lista de elementos o patrón, si se necesita un sustituto, se realizará.
La salida:
Uncleaned: <title>My example: <strong>A text %very% $clean!!</strong></title>
1st clean: My example: A text %very% $clean!!
2nd clean: My example: A text very clean
Tienes que reasignar tu variable str:
for char in line:
if char in " ?.!/;:":
line = line.replace(char,'''')
Usando el filter
, solo necesitarías una línea
line = filter(lambda char: char not in " ?.!/;:", line)
Esto trata la cadena como un iterable y verifica todos los caracteres si la lambda
devuelve True
:
>>> help(filter) Help on built-in function filter in module __builtin__: filter(...) filter(function or None, sequence) -> list, tuple, or string Return those items of sequence for which function(item) is true. If function is None, return the items that are true. If sequence is a tuple or string, return the same type, else return a list.
puedes usar set
charlist = list(set(string.digits+string.ascii_uppercase) - set(''10IO''))
return ''''.join([random.SystemRandom().choice(charlist) for _ in range(passlen)])
#!/usr/bin/python
import re
strs = "how^ much for{} the maple syrup? $20.99? That''s[] ricidulous!!!"
print strs
nstr = re.sub(r''[?|$|.|!|a|b]'',r'' '',strs)#i have taken special character to remove but any #character can be added here
print nstr
nestr = re.sub(r''[^a-zA-Z0-9 ]'',r'''',nstr)#for removing special character
print nestr
>>> # Character stripping
>>> a = ''?abcd1234!!''
>>> t.lstrip(''?'')
''abcd1234!!''
>>> t.strip(''?!'')
''abcd1234''
>>> line = "abc#@!?efg12;:?"
>>> ''''.join( c for c in line if c not in ''?:!/;'' )
''abc#@efg12''
>>> s = ''a1b2c3''
>>> ''''.join(c for c in s if c not in ''123'')
''abc''
line = line.translate(None, " ?.!/;:")