web-dev-qa-db-fra.com

Supprimer tous les caractères non numériques de la chaîne en Python

Comment pouvons-nous supprimer tous les caractères non numériques d'une chaîne en Python?

102
grizzley
>>> import re
>>> re.sub("[^0-9]", "", "sdkjh987978asd098as0980a98sd")
'987978098098098'
202
Ned Batchelder

Pas sûr que ce soit le moyen le plus efficace, mais:

>>> ''.join(c for c in "abc123def456" if c.isdigit())
'123456'

La partie ''.join signifie combiner tous les caractères résultants sans aucun caractère intermédiaire. Ensuite, le reste est une compréhension de liste, où (comme vous pouvez probablement le deviner), nous prenons uniquement les parties de la chaîne qui correspondent à la condition isdigit.

72
Mark Rushakoff

Cela devrait fonctionner pour les chaînes et les objets Unicode:

# python <3.0
def only_numerics(seq):
    return filter(type(seq).isdigit, seq)

# python ≥3.0
def only_numerics(seq):
    seq_type= type(seq)
    return seq_type().join(filter(seq_type.isdigit, seq))
12
tzot

L’approche la plus rapide, si vous devez effectuer plus d’une ou deux opérations de suppression de ce type (ou même une seule, mais sur une très longue chaîne! -), consiste à utiliser la méthode translate de chaînes, même si elle nécessite une préparation :

>>> import string
>>> allchars = ''.join(chr(i) for i in xrange(256))
>>> identity = string.maketrans('', '')
>>> nondigits = allchars.translate(identity, string.digits)
>>> s = 'abc123def456'
>>> s.translate(identity, nondigits)
'123456'

La méthode translate est différente, et peut-être un peu plus simple à utiliser, sur les chaînes Unicode que sur les chaînes d'octet, au fait:

>>> unondig = dict.fromkeys(xrange(65536))
>>> for x in string.digits: del unondig[ord(x)]
... 
>>> s = u'abc123def456'
>>> s.translate(unondig)
u'123456'

Vous voudrez peut-être utiliser une classe de mappage plutôt qu'un dict, en particulier si votre chaîne Unicode peut potentiellement contenir des caractères avec des valeurs ord très élevées (cela rendrait le dict excessivement volumineux ;-). Par exemple:

>>> class keeponly(object):
...   def __init__(self, keep): 
...     self.keep = set(ord(c) for c in keep)
...   def __getitem__(self, key):
...     if key in self.keep:
...       return key
...     return None
... 
>>> s.translate(keeponly(string.digits))
u'123456'
>>> 
5
Alex Martelli

Juste pour ajouter une autre option au mélange, il existe plusieurs constantes utiles dans le module string. Bien que plus utiles dans d'autres cas, ils peuvent être utilisés ici.

>>> from string import digits
>>> ''.join(c for c in "abc123def456" if c in digits)
'123456'

Le module contient plusieurs constantes, notamment:

  • ascii_letters (abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ)
  • hexdigits (0123456789abcdefABCDEF)

Si vous utilisez beaucoup ces constantes, il peut être intéressant de les convertir en frozenset. Cela permet O(1) des recherches, plutôt que O (n), où n est la longueur de la constante pour les chaînes d'origine.

>>> digits = frozenset(digits)
>>> ''.join(c for c in "abc123def456" if c in digits)
'123456'
4
Tim McNamara

@Ned Batchelder et @newacct ont fourni la bonne réponse, mais ...

Juste au cas où vous avez une virgule (,) décimale (.) Dans votre chaîne:

import re
re.sub("[^\d\.]", "", "$1,999,888.77")
'1999888.77'
0
kennyut