web-dev-qa-db-fra.com

Supprimer une liste de caractères dans une chaîne

Je veux supprimer les caractères d'une chaîne en python:

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

Mais j'ai beaucoup de personnages à supprimer. J'ai pensé à une liste

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

Mais comment puis-je utiliser la list pour remplacer les caractères de la string?

206
Laura

Si vous utilisez python2 et que vos entrées sont des chaînes (pas des unicodes), la meilleure méthode est str.translate :

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

Sinon, vous devez prendre en compte les options suivantes:

A. Itérez le caractère sujet par caractère, omettez les caractères indésirables et join la liste résultante:

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

(Notez que la version du générateur ''.join(c for c ...) sera moins efficace).

B. Créez une expression régulière à la volée et re.sub avec une chaîne vide:

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

( re.escape garantit que des caractères tels que ^ ou ] ne casseront pas l'expression régulière).

C. Utilisez la variante mapping de translate :

>>> 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'

Code de test complet et horaires:

#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)

Résultats:

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

(Remarque: le chiffre pour remove_chars_translate_bytes pourrait nous indiquer pourquoi l'industrie hésitait à adopter Unicode pendant une aussi longue période).

254
georg

Vous pouvez utiliser str.translate() :

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

Exemple:

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

Vous pouvez utiliser la méthode translate .

s.translate(None, '!.;,')
35
''.join(c for c in myString if not c in badTokens)
15
ninjagecko

Si vous utilisez python3 et recherchez la solution translate - la fonction a été modifiée et prend désormais 1 paramètre au lieu de 2. 

Ce paramètre est une table (peut être un dictionnaire) où chaque clé est l'ordinal Unicode (int) du caractère à rechercher et la valeur est le remplacement (peut être un ordinal Unicode ou une chaîne à laquelle mapper la clé).

Voici un exemple d'utilisation:

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

Une autre approche utilisant regex: 

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

vous pourriez utiliser quelque chose comme ça

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

Ce code n’est pas le mien et provient de ici c’est un excellent article et explique en profondeur

6
krystan honour

Pourquoi pas une simple boucle?

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

Évitez également de nommer les listes "liste". Il remplace la fonction intégrée list.

6
aIKid

Également un sujet intéressant sur la suppression des accents UTF-8 forme une chaîne convertissant un caractère en son caractère standard non accentué:

Quel est le meilleur moyen de supprimer les accents dans une chaîne python unicode?

extrait de code du sujet:

import unicodedata

def remove_accents(input_str):
    nkfd_form = unicodedata.normalize('NFKD', input_str)
    return u"".join([c for c in nkfd_form if not unicodedata.combining(c)])
3
Sylvain

Peut-être une manière plus moderne et fonctionnelle de réaliser ce que vous souhaitez:

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

veuillez noter que pour ce but particulier, c'est un peu exagéré, mais une fois que vous avez besoin de conditions plus complexes, le filtre est pratique

3
rioted

manière 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)

sortie:

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

2
perfecto25

Ces jours-ci, je plonge dans le programme, et maintenant je pense bien savoir récursir et évaluer. HAHAHA. Juste partager de nouvelles façons:

d'abord, évaluez-le

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

en second lieu, 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)

Hé, ne comptez pas. Je veux juste partager une nouvelle idée.

1
tcpiper

Que diriez-vous de ceci - une ligne. 

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

je pense que c'est assez simple et va faire!

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]

c'est une façon de le faire. Mais si vous êtes fatigué de conserver une liste de caractères à supprimer, vous pouvez le faire en utilisant le numéro d'ordre des chaînes que vous parcourez. le numéro de commande est la valeur ascii de ce caractère. le nombre ascii pour 0 en tant que caractère est 48 et le nombre ascii pour minuscule z est 122, de sorte que:

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]
1
Hiskel Kelemework

Je pense à une solution pour cela. D'abord, je ferais l'entrée de chaîne sous forme de liste. Ensuite, je remplacerais les éléments de la liste. Puis, en utilisant la commande join, je retournerai list sous forme de chaîne. Le code peut être comme ça:

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)

Cela enlèverait n'importe quoi de la chaîne. Qu'est ce que tu penses de ça?

0

Voici une approche more_itertools :

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'

Ici, nous avons divisé les éléments trouvés dans blacklist, aplatissons les résultats et joignons la chaîne.

0
pylang