Rimozione di tutti i caratteri non numerici dalla stringa in Python


Risposte:


267
>>> import re
>>> re.sub("[^0-9]", "", "sdkjh987978asd098as0980a98sd")
'987978098098098'

90
che potrebbe essere re.sub (r "\ D", "", "sdkjh987978asd098as0980a98sd")
newacct

3
e potrebbe essere: dal reimportazione sub
James Koss

89

Non sono sicuro se questo è il modo più efficiente, ma:

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

La ''.joinparte significa combinare tutti i personaggi risultanti insieme senza alcun carattere in mezzo. Quindi il resto è una comprensione dell'elenco, in cui (come probabilmente puoi immaginare) prendiamo solo le parti della stringa che corrispondono alla condizione isdigit.


1
Questo fa il contrario. Penso che intendi "non c.isdigit ()"
Ryan R. Rosario l'

7
Rimuovi tutto non numerico == mantieni solo numerico.
Mark Rushakoff,

10
Mi piace che questo approccio non richieda un richiamo per questa semplice funzione.
triunenatura,

Nota che a differenza delle implementazioni che usano str.translate, questa soluzione funziona sia in Python 2.7 che in 3.4. Grazie!
Alex

1
Preferisco questa alternativa. L'uso di un regex mi sembra eccessivo.
Alfredocambera,

18

Questo dovrebbe funzionare sia per le stringhe che per gli oggetti unicode in Python2 e per entrambe le stringhe e i byte in Python3:

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

9

Solo per aggiungere un'altra opzione al mix, ci sono diverse costanti utili all'interno del stringmodulo. Sebbene più utili in altri casi, possono essere utilizzati qui.

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

Esistono diverse costanti nel modulo, tra cui:

  • ascii_letters (ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz)
  • hexdigits (0123456789abcdefABCDEF)

Se stai usando queste costanti pesantemente, può essere utile convertirle in a frozenset. Ciò abilita le ricerche O (1), anziché O (n), dove n è la lunghezza della costante per le stringhe originali.

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

'' .join (c per c in "abc123def456" se c.isdigit ()) funziona nel mio pitone 3.4
Eino Mäkitalo,

7

@Ned Batchelder e @newacct hanno fornito la risposta giusta, ma ...

Nel caso in cui tu abbia una virgola (,) decimale (.) Nella tua stringa:

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

5

L'approccio più rapido, se è necessario eseguire più di una o due di tali operazioni di rimozione (o anche solo una, ma su una stringa molto lunga! -), è fare affidamento sul translatemetodo delle stringhe, anche se necessita di alcune prep:

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

Il translatemetodo è diverso, e forse un po 'più semplice da usare, sulle stringhe Unicode rispetto alle stringhe di byte, a proposito:

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

Potresti voler usare una classe di mappatura piuttosto che un vero dict, specialmente se la tua stringa Unicode potrebbe potenzialmente contenere caratteri con valori ord molto alti (ciò renderebbe il dict eccessivamente grande ;-). Per esempio:

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

2
(1) Non codificare i numeri magici; s / 65536 / sys.maxunicode / (2) Il dict è incondizionatamente "eccessivamente grande" perché l'input "potrebbe potenzialmente" contenere (sys.maxunicode - number_of_non_numeric_chars)voci. (3) considera se string.digits potrebbe non essere sufficiente portando alla necessità di aprire il modulo unicodedata (4) considera re.sub (r '(? U) \ D +', u '', text) per semplicità e potenziale velocità.
John Machin

2

Molte risposte giuste, ma nel caso tu lo voglia in un float, direttamente, senza usare regex:

x= '$123.45M'

float(''.join(c for c in x if (c.isdigit() or c =='.'))

123.45

È possibile modificare il punto per una virgola in base alle proprie esigenze.

cambia per questo se sai che il tuo numero è un numero intero

x='$1123'    
int(''.join(c for c in x if c.isdigit())

1123

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.