Comment puis-je supprimer tous les caractères sauf les nombres de la chaîne?
Comment puis-je supprimer tous les caractères sauf les nombres de la chaîne?
Réponses:
En Python 2. *, l'approche de loin la plus rapide est la .translateméthode:
>>> x='aaa12333bb445bb54b5b52'
>>> import string
>>> all=string.maketrans('','')
>>> nodigs=all.translate(all, string.digits)
>>> x.translate(all, nodigs)
'1233344554552'
>>>
string.maketransfait une table de traduction (une chaîne de longueur 256) qui dans ce cas est la même que ''.join(chr(x) for x in range(256))(juste plus rapide à faire ;-). .translateapplique la table de traduction (qui ici n'est pas pertinente car allsignifie essentiellement identité) ET supprime les caractères présents dans le deuxième argument - la partie clé.
.translatefonctionne très différemment sur les chaînes Unicode (et les chaînes en Python 3 - Je fais des questions de souhaits spécifiques , qui majeure à libération de Python est intéressant!) - pas tout à fait ce simple, pas tout à fait ce jeûne, mais encore tout à fait utilisable.
De retour à 2. *, la différence de performances est impressionnante ...:
$ python -mtimeit -s'import string; all=string.maketrans("", ""); nodig=all.translate(all, string.digits); x="aaa12333bb445bb54b5b52"' 'x.translate(all, nodig)'
1000000 loops, best of 3: 1.04 usec per loop
$ python -mtimeit -s'import re; x="aaa12333bb445bb54b5b52"' 're.sub(r"\D", "", x)'
100000 loops, best of 3: 7.9 usec per loop
Accélérer les choses de 7 à 8 fois n'est guère d'arachides, donc la translateméthode vaut la peine d'être connue et utilisée. L'autre approche non-ER populaire ...:
$ python -mtimeit -s'x="aaa12333bb445bb54b5b52"' '"".join(i for i in x if i.isdigit())'
100000 loops, best of 3: 11.5 usec per loop
est 50% plus lent que RE, donc l' .translateapproche la bat de plus d'un ordre de grandeur.
Dans Python 3, ou pour Unicode, vous devez passer .translateun mappage (avec des ordinaux, et non des caractères directement, comme clés) qui renvoie Nonece que vous voulez supprimer. Voici un moyen pratique d'exprimer cela pour supprimer "tout sauf" quelques caractères:
import string
class Del:
def __init__(self, keep=string.digits):
self.comp = dict((ord(c),c) for c in keep)
def __getitem__(self, k):
return self.comp.get(k)
DD = Del()
x='aaa12333bb445bb54b5b52'
x.translate(DD)
émet également '1233344554552'. Cependant, en mettant cela dans xx.py, nous avons ...:
$ python3.1 -mtimeit -s'import re; x="aaa12333bb445bb54b5b52"' 're.sub(r"\D", "", x)'
100000 loops, best of 3: 8.43 usec per loop
$ python3.1 -mtimeit -s'import xx; x="aaa12333bb445bb54b5b52"' 'x.translate(xx.DD)'
10000 loops, best of 3: 24.3 usec per loop
... ce qui montre que l'avantage de performance disparaît, pour ce genre de tâches de «suppression», et devient une diminution des performances.
x.translate(None, string.digits)aboutit en fait 'aaabbbbbb', ce qui est le contraire de ce qui est prévu.
allbuiltin ... pas sûr!
Utilisez re.sub, comme ceci:
>>> import re
>>> re.sub('\D', '', 'aas30dsa20')
'3020'
\D correspond à n'importe quel caractère non numérique, donc le code ci-dessus remplace essentiellement chaque caractère non numérique de la chaîne vide.
Ou vous pouvez utiliser filter, comme ça (en Python 2):
>>> filter(str.isdigit, 'aas30dsa20')
'3020'
Puisque dans Python 3, filterrenvoie un itérateur au lieu de a list, vous pouvez utiliser ce qui suit à la place:
>>> ''.join(filter(str.isdigit, 'aas30dsa20'))
'3020'
isdigit, le générateur avec isdigtest à mi-chemin entre eux
rpour la chaîne brute:re.sub(r"\D+", "", "aas30dsa20")
s=''.join(i for i in s if i.isdigit())
Une autre variante de générateur.
Vous pouvez utiliser le filtre:
filter(lambda x: x.isdigit(), "dasdasd2313dsa")
Sur python3.0, vous devez rejoindre ceci (un peu moche :()
''.join(filter(lambda x: x.isdigit(), "dasdasd2313dsa"))
stren listpour vous assurer qu'il fonctionne à la fois sur py2 et py3:''.join(filter(lambda x: x.isdigit(), list("dasdasd2313dsa")))
dans le sens de la réponse de Bayer:
''.join(i for i in s if i.isdigit())
-n'est pas un chiffre.
x.translate(None, string.digits)
supprimera tous les chiffres de la chaîne. Pour supprimer des lettres et conserver les chiffres, procédez comme suit:
x.translate(None, string.letters)
TypeError: translate () prend exactement un argument (2 donnés). Pourquoi cette question a été votée à la hausse dans son état actuel est assez frustrante.
L'op mentionne dans les commentaires qu'il souhaite conserver la décimale. Cela peut être fait avec la méthode re.sub (selon la seconde et la meilleure réponse à mon humble avis) en énumérant explicitement les caractères à conserver, par exemple
>>> re.sub("[^0123456789\.]","","poo123.4and5fish")
'123.45'
Une version rapide pour Python 3:
# xx3.py
from collections import defaultdict
import string
_NoneType = type(None)
def keeper(keep):
table = defaultdict(_NoneType)
table.update({ord(c): c for c in keep})
return table
digit_keeper = keeper(string.digits)
Voici une comparaison des performances par rapport à l'expression régulière:
$ python3.3 -mtimeit -s'import xx3; x="aaa12333bb445bb54b5b52"' 'x.translate(xx3.digit_keeper)'
1000000 loops, best of 3: 1.02 usec per loop
$ python3.3 -mtimeit -s'import re; r = re.compile(r"\D"); x="aaa12333bb445bb54b5b52"' 'r.sub("", x)'
100000 loops, best of 3: 3.43 usec per loop
C'est donc un peu plus de 3 fois plus rapide que les regex, pour moi. C'est aussi plus rapide que class Delci-dessus, car defaultdictfait toutes ses recherches en C, plutôt qu'en Python (lent). Voici cette version sur mon même système, à titre de comparaison.
$ python3.3 -mtimeit -s'import xx; x="aaa12333bb445bb54b5b52"' 'x.translate(xx.DD)'
100000 loops, best of 3: 13.6 usec per loop
Moche mais fonctionne:
>>> s
'aaa12333bb445bb54b5b52'
>>> a = ''.join(filter(lambda x : x.isdigit(), s))
>>> a
'1233344554552'
>>>
list(s)?
filter(lambda x: x.isdigit(), s)a bien fonctionné pour moi. ... oh, c'est parce que j'utilise Python 2.7.
$ python -mtimeit -s'import re; x="aaa12333bb445bb54b5b52"' 're.sub(r"\D", "", x)'
100000 boucles, meilleur de 3: 2,48 usec par boucle
$ python -mtimeit -s'import re; x="aaa12333bab445bb54b5b52"' '"".join(re.findall("[a-z]+",x))'
100000 boucles, meilleur de 3: 2,02 usec par boucle
$ python -mtimeit -s'import re; x="aaa12333bb445bb54b5b52"' 're.sub(r"\D", "", x)'
100000 boucles, meilleur de 3: 2,37 usec par boucle
$ python -mtimeit -s'import re; x="aaa12333bab445bb54b5b52"' '"".join(re.findall("[a-z]+",x))'
100000 boucles, meilleur de 3: 1,97 usec par boucle
J'avais observé que la jointure est plus rapide que les sous.
Vous pouvez lire chaque caractère. S'il s'agit d'un chiffre, incluez-le dans la réponse. La str.isdigit() méthode est un moyen de savoir si un caractère est un chiffre.
your_input = '12kjkh2nnk34l34'
your_output = ''.join(c for c in your_input if c.isdigit())
print(your_output) # '1223434'
J'ai utilisé ça. 'letters'doit contenir toutes les lettres dont vous souhaitez vous débarrasser:
Output = Input.translate({ord(i): None for i in 'letters'}))
Exemple:
Input = "I would like 20 dollars for that suit"
Output = Input.translate({ord(i): None for i in 'abcdefghijklmnopqrstuvwxzy'}))
print(Output)
Production:
20