Enlever tout sauf les caractères alphanumériques d'une chaîne en Python

Quelle est la meilleure façon de supprimer tous les caractères non alphanumériques d'une chaîne, en utilisant Python?

les solutions présentées dans la variante de PHP de cette question fonctionneront probablement avec quelques ajustements mineurs, mais ne me semblent pas très "pythonic".

pour information, Je ne veux pas seulement rayer les périodes et les virgules (et autres signes de ponctuation), mais aussi les citations, les parenthèses, etc.

242
demandé sur Community 2009-08-14 12:54:47

7 réponses

je viens de chronométrer quelques fonctions par curiosité. Dans ces tests, je supprime les caractères non alphanumériques de la chaîne de caractères string.printable (qui fait partie du module intégré string ).

$ python -m timeit -s \
     "import string" \
     "''.join(ch for ch in string.printable if ch.isalnum())" 
10000 loops, best of 3: 57.6 usec per loop

$ python -m timeit -s \
    "import string" \
    "filter(str.isalnum, string.printable)"                 
10000 loops, best of 3: 37.9 usec per loop

$ python -m timeit -s \
    "import re, string" \
    "re.sub('[\W_]', '', string.printable)"
10000 loops, best of 3: 27.5 usec per loop

$ python -m timeit -s \
    "import re, string" \
    "re.sub('[\W_]+', '', string.printable)"                
100000 loops, best of 3: 15 usec per loop

$ python -m timeit -s \
    "import re, string; pattern = re.compile('[\W_]+')" \
    "pattern.sub('', string.printable)" 
100000 loops, best of 3: 11.2 usec per loop
259
répondu Otto Allmendinger 2016-04-15 19:00:15

expressions régulières à la rescousse:

import re
re.sub(r'\W+', '', your_string)

par définition de Python '\W = = [^a-zA-Z0-9_] , ce qui exclut tous les numbers , letters et _

182
répondu Ants Aasma 2018-01-01 23:44:55

utiliser le str.translate() la méthode.

présumant que vous le ferez souvent:

(1) Une fois, créez une chaîne de caractères contenant tous les caractères que vous souhaitez supprimer:

delchars = ''.join(c for c in map(chr, range(256)) if not c.isalnum())

(2) chaque fois que vous voulez broyer une corde:

scrunched = s.translate(None, delchars)

le coût d'installation se compare probablement favorablement avec re.le coût marginal est beaucoup plus faible:

C:\junk>\python26\python -mtimeit -s"import string;d=''.join(c for c in map(chr,range(256)) if not c.isalnum());s=string.printable" "s.translate(None,d)"
100000 loops, best of 3: 2.04 usec per loop

C:\junk>\python26\python -mtimeit -s"import re,string;s=string.printable;r=re.compile(r'[\W_]+')" "r.sub('',s)"
100000 loops, best of 3: 7.34 usec per loop

Note: utilisant une chaîne de caractères.imprimable comme données de référence donne au modèle '[\W_]+ ' un avantage indu ; tous les caractères non-alphanumériques sont dans un groupe ... dans les données Types, il y aurait plus d'une substitution à faire:

C:\junk>\python26\python -c "import string; s = string.printable; print len(s),repr(s)"
100 '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&\'()*+,-./:;=>?@[\]^_`{|}~ \t\n\r\x0b\x0c'

voici ce qui se passe si vous donnez re.sous un peu plus de travail à faire:

C:\junk>\python26\python -mtimeit -s"d=''.join(c for c in map(chr,range(256)) if not c.isalnum());s='foo-'*25" "s.translate(None,d)"
1000000 loops, best of 3: 1.97 usec per loop

C:\junk>\python26\python -mtimeit -s"import re;s='foo-'*25;r=re.compile(r'[\W_]+')" "r.sub('',s)"
10000 loops, best of 3: 26.4 usec per loop
64
répondu John Machin 2009-08-15 00:33:48

Vous pouvez essayer:

print ''.join(ch for ch in some_string if ch.isalnum())
35
répondu ars 2009-08-14 09:02:28
>>> import re
>>> string = "Kl13@£$%[};'\""
>>> pattern = re.compile('\W')
>>> string = re.sub(pattern, '', string)
>>> print string
Kl13
13
répondu DisplacedAussie 2009-08-14 09:01:22

Que Diriez-vous de:

def ExtractAlphanumeric(InputString):
    from string import ascii_letters, digits
    return "".join([ch for ch in InputString if ch in (ascii_letters + digits)])

cela fonctionne en utilisant la compréhension de liste pour produire une liste des caractères dans InputString s'ils sont présents dans les chaînes combinées ascii_letters et digits . Il réunit ensuite la liste en une chaîne.

11
répondu DrAl 2009-08-14 09:05:16

comme un spin off de quelques autres réponses ici, j'offre une façon vraiment simple et flexible pour définir un ensemble de caractères que vous voulez limiter le contenu d'une chaîne de caractères. Dans ce cas, j'autorise les caractères alphanumériques PLUS le tiret et le trait de soulignement. Il suffit d'ajouter ou de supprimer des caractères de mon PERMITTED_CHARS comme convient à votre cas d'utilisation.

PERMITTED_CHARS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-" 
someString = "".join(c for c in someString if c in PERMITTED_CHARS)
2
répondu BuvinJ 2017-03-13 12:54:22