Come posso rimuovere tutti i caratteri tranne i numeri dalla stringa?
Come posso rimuovere tutti i caratteri tranne i numeri dalla stringa?
Risposte:
In Python 2. *, l'approccio di gran lunga più veloce è il .translate
metodo:
>>> x='aaa12333bb445bb54b5b52'
>>> import string
>>> all=string.maketrans('','')
>>> nodigs=all.translate(all, string.digits)
>>> x.translate(all, nodigs)
'1233344554552'
>>>
string.maketrans
crea una tabella di traduzione (una stringa di lunghezza 256) che in questo caso è la stessa ''.join(chr(x) for x in range(256))
(solo più veloce da realizzare ;-). .translate
applica la tabella di traduzione (che qui è irrilevante poiché all
essenzialmente significa identità) E cancella i caratteri presenti nel secondo argomento - la parte chiave.
.translate
funziona in modo molto diverso sulle stringhe Unicode (e sulle stringhe in Python 3 - I do domande dei desideri specificare che major release di Python è di interesse!) - non del tutto questo semplice, non del tutto così veloce, anche se ancora abbastanza usabile.
Torna a 2. *, la differenza di prestazioni è impressionante ...:
$ 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
Accelerare le cose di 7-8 volte non è certo arachidi, quindi translate
vale la pena conoscere e utilizzare il metodo. L'altro approccio non-RE popolare ...:
$ python -mtimeit -s'x="aaa12333bb445bb54b5b52"' '"".join(i for i in x if i.isdigit())'
100000 loops, best of 3: 11.5 usec per loop
è il 50% più lento di RE, quindi l' .translate
approccio lo supera di un ordine di grandezza.
In Python 3, o per Unicode, è necessario passare .translate
una mappatura (con ordinali, non direttamente i caratteri, come chiavi) che ritorna None
per ciò che si desidera eliminare. Ecco un modo conveniente per esprimere questo per la cancellazione di "tutto tranne" alcuni caratteri:
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)
emette anche '1233344554552'
. Tuttavia, inserendo questo in xx.py abbiamo ...:
$ 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
... che mostra il vantaggio in termini di prestazioni scompare, per questo tipo di attività di "eliminazione", e diventa una riduzione delle prestazioni.
x.translate(None, string.digits)
in realtà risulta 'aaabbbbbb'
, che è l'opposto di ciò che si intende.
all
incorporato ... non ne sono sicuro!
Utilizzare in questo re.sub
modo:
>>> import re
>>> re.sub('\D', '', 'aas30dsa20')
'3020'
\D
corrisponde a qualsiasi carattere non numerico, pertanto il codice sopra riportato sostituisce essenzialmente ogni carattere non numerico per la stringa vuota.
Oppure puoi usare filter
, in questo modo (in Python 2):
>>> filter(str.isdigit, 'aas30dsa20')
'3020'
Poiché in Python 3, filter
restituisce un iteratore anziché un list
, puoi invece utilizzare quanto segue:
>>> ''.join(filter(str.isdigit, 'aas30dsa20'))
'3020'
isdigit
, il generatore con isdigt
è a metà strada tra loro
r
per stringa grezza:re.sub(r"\D+", "", "aas30dsa20")
s=''.join(i for i in s if i.isdigit())
Un'altra variante del generatore.
Puoi usare il filtro:
filter(lambda x: x.isdigit(), "dasdasd2313dsa")
Su python3.0 devi unirti a questo (un pò brutto :()
''.join(filter(lambda x: x.isdigit(), "dasdasd2313dsa"))
str
in list
per assicurarti che funzioni sia su py2 che su py3:''.join(filter(lambda x: x.isdigit(), list("dasdasd2313dsa")))
sulla falsariga della risposta di bayer:
''.join(i for i in s if i.isdigit())
-
non è una cifra.
x.translate(None, string.digits)
cancellerà tutte le cifre dalla stringa. Per eliminare le lettere e conservare le cifre, procedere come segue:
x.translate(None, string.letters)
TypeError
: translate () accetta esattamente un argomento (2 dato). Perché questa domanda sia stata votata nel suo stato attuale è abbastanza frustrante.
L'op menziona nei commenti che vuole mantenere il decimale. Questo può essere fatto con il metodo re.sub (secondo il secondo e la migliore risposta IMHO) elencando esplicitamente i caratteri da conservare ad es.
>>> re.sub("[^0123456789\.]","","poo123.4and5fish")
'123.45'
Una versione veloce per 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)
Ecco un confronto delle prestazioni contro regex:
$ 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
Quindi per me è un po 'più di 3 volte più veloce di regex. È anche più veloce di class Del
sopra, perché defaultdict
esegue tutte le sue ricerche in C, piuttosto che (lento) Python. Ecco quella versione sul mio stesso sistema, per confronto.
$ python3.3 -mtimeit -s'import xx; x="aaa12333bb445bb54b5b52"' 'x.translate(xx.DD)'
100000 loops, best of 3: 13.6 usec per loop
Brutto ma funziona:
>>> s
'aaa12333bb445bb54b5b52'
>>> a = ''.join(filter(lambda x : x.isdigit(), s))
>>> a
'1233344554552'
>>>
list(s)
?
filter(lambda x: x.isdigit(), s)
ha funzionato bene per me. ... oh, è perché sto usando Python 2.7.
$ python -mtimeit -s'import re; x="aaa12333bb445bb54b5b52"' 're.sub(r"\D", "", x)'
100000 loop, meglio di 3: 2,48 usec per loop
$ python -mtimeit -s'import re; x="aaa12333bab445bb54b5b52"' '"".join(re.findall("[a-z]+",x))'
100000 loop, meglio di 3: 2,02 usec per loop
$ python -mtimeit -s'import re; x="aaa12333bb445bb54b5b52"' 're.sub(r"\D", "", x)'
100000 loop, meglio di 3: 2,37 usec per loop
$ python -mtimeit -s'import re; x="aaa12333bab445bb54b5b52"' '"".join(re.findall("[a-z]+",x))'
100000 loop, meglio di 3: 1,97 usec per loop
Avevo osservato che il join è più veloce del sub.
Puoi leggere ogni personaggio. Se è una cifra, includila nella risposta. Il str.isdigit()
metodo è un modo per sapere se un carattere è una cifra.
your_input = '12kjkh2nnk34l34'
your_output = ''.join(c for c in your_input if c.isdigit())
print(your_output) # '1223434'
Ho usato questo 'letters'
dovrebbe contenere tutte le lettere di cui vuoi sbarazzarti:
Output = Input.translate({ord(i): None for i in 'letters'}))
Esempio:
Input = "I would like 20 dollars for that suit"
Output = Input.translate({ord(i): None for i in 'abcdefghijklmnopqrstuvwxzy'}))
print(Output)
Produzione:
20