Jak mogę usunąć wszystkie znaki z wyjątkiem liczb z ciągu?
Jak mogę usunąć wszystkie znaki z wyjątkiem liczb z ciągu?
Odpowiedzi:
W Pythonie 2. * zdecydowanie najszybszym podejściem jest .translatemetoda:
>>> x='aaa12333bb445bb54b5b52'
>>> import string
>>> all=string.maketrans('','')
>>> nodigs=all.translate(all, string.digits)
>>> x.translate(all, nodigs)
'1233344554552'
>>>
string.maketranstworzy tablicę tłumaczeń (ciąg o długości 256), która w tym przypadku jest taka sama jak ''.join(chr(x) for x in range(256))(tylko szybsza do wykonania ;-). .translatestosuje tabelę tłumaczeń (która tutaj nie ma znaczenia, ponieważ allzasadniczo oznacza tożsamość) ORAZ usuwa znaki obecne w drugim argumencie - części kluczowej.
.translatedziała bardzo różnie na Unicode (i smyczki w Pythonie 3 - I zrobić pytania życzenie określony których głównym uwalnianiu Pythona ma znaczenie!) - nie całkiem to proste, to nie dość szybko, choć nadal bardzo użyteczny.
Wracając do 2. *, różnica w wydajności jest imponująca ...:
$ 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
Przyspieszenie tempa 7-8 razy to nie grosze, więc translatewarto znać i stosować tę metodę. Inne popularne podejście non-RE ...:
$ python -mtimeit -s'x="aaa12333bb445bb54b5b52"' '"".join(i for i in x if i.isdigit())'
100000 loops, best of 3: 11.5 usec per loop
jest o 50% wolniejszy niż RE, więc .translatepodejście przebija go o ponad rząd wielkości.
W Pythonie 3 lub w Unicode musisz przekazać .translateodwzorowanie (z liczbami porządkowymi, a nie znakami bezpośrednio, jako klucze), które zwraca Noneto, co chcesz usunąć. Oto wygodny sposób wyrażenia tego w celu usunięcia „wszystkiego oprócz” kilku znaków:
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)
również emituje '1233344554552'. Jednak umieszczając to w xx.py mamy ...:
$ 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
... co pokazuje, że przewaga wydajności znika w przypadku tego rodzaju zadań „usuwania” i staje się spadkiem wydajności.
x.translate(None, string.digits)w rzeczywistości skutkuje 'aaabbbbbb', co jest przeciwieństwem tego, co jest zamierzone.
allwbudowanego ... nie jestem tego pewien!
Użyj re.sub, tak jak to:
>>> import re
>>> re.sub('\D', '', 'aas30dsa20')
'3020'
\D dopasowuje dowolny znak niecyfrowy, więc powyższy kod zasadniczo zastępuje każdy znak niecyfrowy w pustym łańcuchu.
Lub możesz użyć filter, na przykład (w Pythonie 2):
>>> filter(str.isdigit, 'aas30dsa20')
'3020'
Ponieważ w Pythonie 3 filterzwraca iterator zamiast alist , możesz zamiast tego użyć następującego:
>>> ''.join(filter(str.isdigit, 'aas30dsa20'))
'3020'
isdigit, generator w isdigtpołowie drogi między nimi
rdla nieprzetworzonego ciągu:re.sub(r"\D+", "", "aas30dsa20")
Możesz użyć filtra:
filter(lambda x: x.isdigit(), "dasdasd2313dsa")
Na pythonie 3.0 musisz dołączyć do tego (trochę brzydkie :()
''.join(filter(lambda x: x.isdigit(), "dasdasd2313dsa"))
strna, listaby upewnić się, że działa zarówno na py2, jak i py3:''.join(filter(lambda x: x.isdigit(), list("dasdasd2313dsa")))
zgodnie z odpowiedzią Bayera:
''.join(i for i in s if i.isdigit())
-nie jest cyfrą.
x.translate(None, string.digits)
usunie wszystkie cyfry z ciągu. Aby usunąć litery i zachować cyfry, wykonaj następujące czynności:
x.translate(None, string.letters)
TypeError: translate () przyjmuje dokładnie jeden argument (podane 2). Dlaczego głosowano za tym pytaniem w obecnym stanie, jest dość frustrujące.
Opcja wspomina w komentarzach, że chce zachować miejsce dziesiętne. Można to zrobić za pomocą metody re.sub (zgodnie z drugą i najlepszą odpowiedzią IMHO), jawnie wymieniając znaki, które mają być zachowane, np.
>>> re.sub("[^0123456789\.]","","poo123.4and5fish")
'123.45'
Szybka wersja dla Pythona 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)
Oto porównanie wydajności z wyrażeniem regularnym:
$ 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
Jak dla mnie jest to trochę ponad 3 razy szybsze niż regex. Jest również szybszy niż class Delpowyżej, ponieważ defaultdictwszystkie wyszukiwania wykonuje w C, a nie (powolny) Python. Oto ta wersja w moim systemie dla porównania.
$ python3.3 -mtimeit -s'import xx; x="aaa12333bb445bb54b5b52"' 'x.translate(xx.DD)'
100000 loops, best of 3: 13.6 usec per loop
Brzydki, ale działa:
>>> s
'aaa12333bb445bb54b5b52'
>>> a = ''.join(filter(lambda x : x.isdigit(), s))
>>> a
'1233344554552'
>>>
list(s)?
filter(lambda x: x.isdigit(), s)działało dobrze dla mnie. ... och, to dlatego, że używam Pythona 2.7.
$ python -mtimeit -s'import re; x="aaa12333bb445bb54b5b52"' 're.sub(r"\D", "", x)'
100000 pętli, najlepiej 3: 2,48 usek na pętlę
$ python -mtimeit -s'import re; x="aaa12333bab445bb54b5b52"' '"".join(re.findall("[a-z]+",x))'
100000 pętli, najlepiej 3: 2,02 usek na pętlę
$ python -mtimeit -s'import re; x="aaa12333bb445bb54b5b52"' 're.sub(r"\D", "", x)'
100000 pętli, najlepiej 3: 2,37 usek na pętlę
$ python -mtimeit -s'import re; x="aaa12333bab445bb54b5b52"' '"".join(re.findall("[a-z]+",x))'
100000 pętli, najlepiej 3: 1,97 usek na pętlę
Zauważyłem, że łączenie jest szybsze niż sub.
Możesz przeczytać każdą postać. Jeśli jest cyfrą, dołącz ją do odpowiedzi. str.isdigit() Metoda jest sposobem, aby wiedzieć, czy znak jest cyfra.
your_input = '12kjkh2nnk34l34'
your_output = ''.join(c for c in your_input if c.isdigit())
print(your_output) # '1223434'
Użyłem tego. 'letters'powinien zawierać wszystkie litery, których chcesz się pozbyć:
Output = Input.translate({ord(i): None for i in 'letters'}))
Przykład:
Input = "I would like 20 dollars for that suit"
Output = Input.translate({ord(i): None for i in 'abcdefghijklmnopqrstuvwxzy'}))
print(Output)
Wynik:
20