Suppression d'une liste de caractères dans la chaîne


217

Je veux supprimer des caractères dans une chaîne en python:

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

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

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

Mais comment puis-je utiliser le listpour remplacer les caractères dans le string?


6
Voir stackoverflow.com/questions/1919096/… pour diverses solutions et une belle comparaison.
Martijn de Milliano

Il est dommage que Python (qui est censé venir avec des piles incluses) ne gère pas ce cas d'utilisation hors de la boîte. La fonction PHP str_replace le fait - vous pouvez passer un tableau comme premier argument et une chaîne comme deuxième ( php.net/manual/pl/function.str-replace.php ).
JustAC0der

Réponses:


265

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, il y a les options suivantes à considérer:

A. Répétez le sujet sujet par caractère, omettez les caractères indésirables et joinla 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.subavec une chaîne vide:

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

( re.escapegarantit que des caractères comme^ ou ]ne cassent pas l'expression régulière).

C. Utilisez la variante de mappage 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'

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

(En guise de remarque, le chiffre pour remove_chars_translate_bytespourrait nous donner une idée pourquoi l'industrie était réticente à adopter Unicode pendant si longtemps).


1
La deuxième méthode génère une erreur TypeError: translate() takes exactly one argument (2 given). Apparemment, il prend dict comme argument.
antonavy

@antonavy - la 2ème solution fonctionne - mais seule la chaîne n'est pas unicode (pour laquelle une traduction différente () est nécessaire)
FuzzyAmi

112

Vous pouvez utiliser str.translate():

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

Exemple:

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

19
@ thg435: Personne ne l'a demandé, mais de toute façon:s.translate(dict.fromkeys(map(ord, u",!.;")))
Sven Marnach

2
Cette réponse simultanée (et celle de @ PraveenGollakota) est exactement ce que @Laura a demandé et devrait être la (les) réponse (s) préférée (s).
plaques de cuisson

7
pourquoi python3: TypeError: translate () prend exactement un argument (2 donnés)
Gank

2
@Gank: La unicode.translate()méthode a des paramètres différents de la str.translate()méthode. Utilisez la variante dans le commentaire ci-dessus pour les objets Unicode.
Sven Marnach

@SvenMarnach qu'est-ce que map (ord, u ",!.;"))? et est-ce que vous représentez unicode?
Jun711


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

Utile dans des cas similaires non basés sur des caractères et des chaînes +1
Wolf

12

Si vous utilisez python3 et cherchez la translatesolution - 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 soit 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'

8

Une autre approche utilisant regex:

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

7

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

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 vient d' ici, c'est un excellent article et explique en profondeur ce



3

Peut-être une façon plus moderne et fonctionnelle d'atteindre ce que vous souhaitez:

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

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


Notez également que cela peut tout aussi facilement être fait avec des listes de compréhension, ce qui est beaucoup plus pythonique à mon avis.
émeute

3

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)

production:

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


1

Que diriez-vous de cela - une doublure.

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

1

je pense que c'est assez simple et fera l'affaire!

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 en avez assez de conserver une liste de caractères que vous souhaitez supprimer, vous pouvez le faire en utilisant le numéro de commande des chaînes que vous parcourez. le numéro de commande est la valeur ascii de ce caractère. le nombre ascii pour 0 comme caractère est 48 et le nombre ascii pour minuscule z est 122 donc:

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

Ces jours-ci, je plonge dans le régime, et maintenant je pense que je suis bon en récurrence et en évaluation. HAHAHA. Partagez simplement de nouvelles façons:

d'abord, évaluez-le

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

deuxièmement, récusez-le

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 dévalorisez pas. Je veux juste partager une nouvelle idée.


0

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

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 supprimerait n'importe quoi de la chaîne. Qu'est ce que tu penses de ça?


0

Voici une more_itertoolsapproche:

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 séparons les éléments trouvés dans le blacklist, aplatissons les résultats et joignons la chaîne.


0

Python 3, implémentation de la compréhension de liste sur une seule ligne.

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

Retirer *%,&@! à partir de la chaîne inférieure:

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  
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.