Eliminar una lista de caracteres en cadena


217

Quiero eliminar caracteres en una cadena en python:

string.replace(',', '').replace("!", '').replace(":", '').replace(";", '')...

Pero tengo muchos personajes que tengo que eliminar. Pensé en una lista

list = [',', '!', '.', ';'...]

Pero, ¿cómo puedo usar el listpara reemplazar los caracteres en el string?


66
Consulte stackoverflow.com/questions/1919096/… para obtener varias soluciones y una buena comparación.
Martijn de Milliano

Es una pena que Python (que se dice que viene con baterías incluidas) no maneja este caso de uso fuera de la caja. La función str_replace de PHP lo hace: puede pasar una matriz como primer argumento y una cadena como el segundo ( php.net/manual/pl/function.str-replace.php ).
JustAC0der

Respuestas:


265

Si está utilizando python2 y sus entradas son cadenas (no unicodes), el mejor método es str.translate:

>>> chars_to_remove = ['.', '!', '?']
>>> subj = 'A.B!C?'
>>> subj.translate(None, ''.join(chars_to_remove))
'ABC'

De lo contrario, hay siguientes opciones a considerar:

A. Itere el tema char por char, omita los caracteres no deseados y joinla lista resultante:

>>> sc = set(chars_to_remove)
>>> ''.join([c for c in subj if c not in sc])
'ABC'

(Tenga en cuenta que la versión del generador ''.join(c for c ...) será menos eficiente).

B. Cree una expresión regular sobre la marcha y re.subcon una cadena vacía:

>>> import re
>>> rx = '[' + re.escape(''.join(chars_to_remove)) + ']'
>>> re.sub(rx, '', subj)
'ABC'

( re.escapeasegura que los caracteres como ^o] no rompan la expresión regular).

C. Use la variante de mapeo detranslate :

>>> chars_to_remove = [u'δ', u'Γ', u'ж']
>>> subj = u'AжBδCΓ'
>>> dd = {ord(c):None for c in chars_to_remove}
>>> subj.translate(dd)
u'ABC'

Código de prueba completo y tiempos:

#coding=utf8

import re

def remove_chars_iter(subj, chars):
    sc = set(chars)
    return ''.join([c for c in subj if c not in sc])

def remove_chars_re(subj, chars):
    return re.sub('[' + re.escape(''.join(chars)) + ']', '', subj)

def remove_chars_re_unicode(subj, chars):
    return re.sub(u'(?u)[' + re.escape(''.join(chars)) + ']', '', subj)

def remove_chars_translate_bytes(subj, chars):
    return subj.translate(None, ''.join(chars))

def remove_chars_translate_unicode(subj, chars):
    d = {ord(c):None for c in chars}
    return subj.translate(d)

import timeit, sys

def profile(f):
    assert f(subj, chars_to_remove) == test
    t = timeit.timeit(lambda: f(subj, chars_to_remove), number=1000)
    print ('{0:.3f} {1}'.format(t, f.__name__))

print (sys.version)
PYTHON2 = sys.version_info[0] == 2

print ('\n"plain" string:\n')

chars_to_remove = ['.', '!', '?']
subj = 'A.B!C?' * 1000
test = 'ABC' * 1000

profile(remove_chars_iter)
profile(remove_chars_re)

if PYTHON2:
    profile(remove_chars_translate_bytes)
else:
    profile(remove_chars_translate_unicode)

print ('\nunicode string:\n')

if PYTHON2:
    chars_to_remove = [u'δ', u'Γ', u'ж']
    subj = u'AжBδCΓ'
else:
    chars_to_remove = ['δ', 'Γ', 'ж']
    subj = 'AжBδCΓ'

subj = subj * 1000
test = 'ABC' * 1000

profile(remove_chars_iter)

if PYTHON2:
    profile(remove_chars_re_unicode)
else:
    profile(remove_chars_re)

profile(remove_chars_translate_unicode)

Resultados:

2.7.5 (default, Mar  9 2014, 22:15:05) 
[GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.0.68)]

"plain" string:

0.637 remove_chars_iter
0.649 remove_chars_re
0.010 remove_chars_translate_bytes

unicode string:

0.866 remove_chars_iter
0.680 remove_chars_re_unicode
1.373 remove_chars_translate_unicode

---

3.4.2 (v3.4.2:ab2c023a9432, Oct  5 2014, 20:42:22) 
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)]

"plain" string:

0.512 remove_chars_iter
0.574 remove_chars_re
0.765 remove_chars_translate_unicode

unicode string:

0.817 remove_chars_iter
0.686 remove_chars_re
0.876 remove_chars_translate_unicode

(Como nota al margen, la cifra remove_chars_translate_bytespodría darnos una pista de por qué la industria era reacia a adoptar Unicode durante tanto tiempo).


1
El segundo método genera un error TypeError: translate() takes exactly one argument (2 given). Aparentemente toma dict como argumento.
antonavy

@antonavy: la segunda solución funciona, pero solo la cadena no es unicode (para lo cual se necesita un traductor diferente)
FuzzyAmi

112

Puedes usar str.translate():

s.translate(None, ",!.;")

Ejemplo:

>>> s = "asjo,fdjk;djaso,oio!kod.kjods;dkps"
>>> s.translate(None, ",!.;")
'asjofdjkdjasooiokodkjodsdkps'

19
@ thg435: Nadie pidió esto, pero de todos modos:s.translate(dict.fromkeys(map(ord, u",!.;")))
Sven Marnach

2
Esta (y la respuesta simultánea de @ PraveenGollakota) es exactamente lo que pidió @Laura y debería ser la (s) respuesta (s) preferida (s).
Hobs

77
por qué python3: TypeError: translate () toma exactamente un argumento (2 dados)
Gank

2
@Gank: El unicode.translate()método tiene diferentes parámetros que el str.translate()método. Use la variante en el comentario anterior para los objetos Unicode.
Sven Marnach

@SvenMarnach ¿Qué es el mapa (ord, u ",!.;"))? y representas unicode?
Jun711


16
''.join(c for c in myString if not c in badTokens)

Útil en casos similares no basados ​​en caracteres y cadenas +1
Wolf

12

Si está utilizando python3 y está buscando eltranslate solución, la función se cambió y ahora toma 1 parámetro en lugar de 2.

Ese parámetro es una tabla (puede ser un diccionario) donde cada clave es el ordinal Unicode (int) del carácter a buscar y el valor es el reemplazo (puede ser un ordinal Unicode o una cadena para asignar la clave).

Aquí hay un ejemplo de uso:

>>> list = [',', '!', '.', ';']
>>> s = "This is, my! str,ing."
>>> s.translate({ord(x): '' for x in list})
'This is my string'

8

Otro enfoque usando regex:

''.join(re.split(r'[.;!?,]', s))

7

¿Por qué no un simple bucle?

for i in replace_list:
    string = string.replace(i, '')

Además, evite nombrar listas 'lista'. Anula la función incorporada list.


6

podrías usar algo como esto

def replace_all(text, dic):
  for i, j in dic.iteritems():
    text = text.replace(i, j)
  return text

Este código no es mío y viene de aquí, es un gran artículo y discute en profundidad haciendo esto



3

Quizás una forma más moderna y funcional de lograr lo que deseas:

>>> subj = 'A.B!C?'
>>> list = set([',', '!', '.', ';', '?'])
>>> filter(lambda x: x not in list, subj)
'ABC'

tenga en cuenta que para este propósito en particular es una exageración, pero una vez que necesita condiciones más complejas, el filtro es útil


También tenga en cuenta que esto se puede hacer fácilmente con las comprensiones de listas, que en mi opinión es mucho más pitónico.
Disturbó el

3

manera simple,

import re
str = 'this is string !    >><< (foo---> bar) @-tuna-#   sandwich-%-is-$-* good'

// condense multiple empty spaces into 1
str = ' '.join(str.split()

// replace empty space with dash
str = str.replace(" ","-")

// take out any char that matches regex
str = re.sub('[!@#$%^&*()_+<>]', '', str)

salida:

this-is-string--foo----bar--tuna---sandwich--is---good


1

¿Qué tal esto?

reduce(lambda x,y : x.replace(y,"") ,[',', '!', '.', ';'],";Test , ,  !Stri!ng ..")

1

Creo que esto es bastante simple y lo hará!

list = [",",",","!",";",":"] #the list goes on.....

theString = "dlkaj;lkdjf'adklfaj;lsd'fa'dfj;alkdjf" #is an example string;
newString="" #the unwanted character free string
for i in range(len(TheString)):
    if theString[i] in list:
        newString += "" #concatenate an empty string.
    else:
        newString += theString[i]

Esta es una manera de hacerlo. Pero si está cansado de mantener una lista de caracteres que desea eliminar, puede hacerlo utilizando el número de orden de las cadenas por las que itera. El número de orden es el valor ASCII de ese carácter. el número ascii para 0 como un carácter es 48 y el número ascii para z minúscula es 122, entonces:

theString = "lkdsjf;alkd8a'asdjf;lkaheoialkdjf;ad"
newString = ""
for i in range(len(theString)):
     if ord(theString[i]) < 48 or ord(theString[i]) > 122: #ord() => ascii num.
         newString += ""
     else:
        newString += theString[i]

0

En estos días me estoy sumergiendo en el esquema, y ​​ahora creo que soy bueno recurriendo y evaluando. JAJAJA. Solo comparte algunas formas nuevas:

primero, evalúalo

print eval('string%s' % (''.join(['.replace("%s","")'%i for i in replace_list])))

segundo, recurse

def repn(string,replace_list):
    if replace_list==[]:
        return string
    else:
        return repn(string.replace(replace_list.pop(),""),replace_list)

print repn(string,replace_list)

Oye, no desestimes. Solo quiero compartir alguna idea nueva.


0

Estoy pensando en una solución para esto. Primero, haría la entrada de cadena como una lista. Luego reemplazaría los elementos de la lista. Luego, mediante el uso del comando join, devolveré la lista como una cadena. El código puede ser así:

def the_replacer(text):
    test = []    
    for m in range(len(text)):
        test.append(text[m])
        if test[m]==','\
        or test[m]=='!'\
        or test[m]=='.'\
        or test[m]=='\''\
        or test[m]==';':
    #....
            test[n]=''
    return ''.join(test)

Esto eliminaría cualquier cosa de la cadena. ¿Qué piensas sobre eso?


0

Aquí hay un more_itertoolsenfoque:

import more_itertools as mit


s = "A.B!C?D_E@F#"
blacklist = ".!?_@#"

"".join(mit.flatten(mit.split_at(s, pred=lambda x: x in set(blacklist))))
# 'ABCDEF'

Aquí dividimos los elementos encontrados en el blacklist, aplanamos los resultados y unimos la cadena.


0

Python 3, implementación de comprensión de lista de una sola línea.

from string import ascii_lowercase # 'abcdefghijklmnopqrstuvwxyz'
def remove_chars(input_string, removable):
  return ''.join([_ for _ in input_string if _ not in removable])

print(remove_chars(input_string="Stack Overflow", removable=ascii_lowercase))
>>> 'S O'

0

Eliminar *%,&@! desde abajo cadena:

s = "this is my string,  and i will * remove * these ** %% "
new_string = s.translate(s.maketrans('','','*%,&@!'))
print(new_string)

# output: this is my string  and i will  remove  these  
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.