Як я можу видалити всі символи, крім цифр, із рядка?
Як я можу видалити всі символи, крім цифр, із рядка?
Відповіді:
У Python 2. * на сьогоднішній день найшвидшим підходом є .translateметод:
>>> x='aaa12333bb445bb54b5b52'
>>> import string
>>> all=string.maketrans('','')
>>> nodigs=all.translate(all, string.digits)
>>> x.translate(all, nodigs)
'1233344554552'
>>>
string.maketransскладає таблицю перекладу (рядок довжиною 256), яка в цьому випадку така сама, як ''.join(chr(x) for x in range(256))(просто швидше зробити ;-). .translateзастосовує таблицю перекладу (що тут не має значення, оскільки allпо суті означає ідентичність) І видаляє символи, присутні у другому аргументі - ключовій частині.
.translateпрацює над різними рядками Unicode (і рядки в Python 3 - я хочу , щоб питання, які основні версії Python цікаві!) - не зовсім прості, не дуже швидкі, хоча все ще досить зручні.
Повернення до 2. *, різниця в продуктивності вражає ...:
$ 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
Перевищення речей в 7-8 разів навряд чи арахіс, тому translateметод варто знати і використовувати. Інший популярний підхід, який не стосується РЕ ...:
$ python -mtimeit -s'x="aaa12333bb445bb54b5b52"' '"".join(i for i in x if i.isdigit())'
100000 loops, best of 3: 11.5 usec per loop
на 50% повільніше, ніж РЕ, тому .translateпідхід долає його на порядок більше.
У Python 3 або Unicode вам потрібно передати .translateвідображення (з порядками, а не символами безпосередньо, як ключі), яке повертає Noneте, що ви хочете видалити. Ось зручний спосіб висловити це для видалення кількох символів "все, окрім":
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)
також випромінює '1233344554552'. Однак, помістивши це в xx.py, ми маємо ...:
$ 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
... що показує, що для цього виду завдань "видалення" зникає перевага в продуктивності і зменшується продуктивність.
x.translate(None, string.digits)насправді це призводить до 'aaabbbbbb', що є протилежним тому, що призначено.
allвбудований ... не впевнений у цьому!
Використовуйте re.subтак:
>>> import re
>>> re.sub('\D', '', 'aas30dsa20')
'3020'
\D відповідає будь-якому нецифровому символу, тому, наведений вище код, по суті замінює кожен нецифровий символ для порожнього рядка.
Або ви можете використовувати filter, як так (у Python 2):
>>> filter(str.isdigit, 'aas30dsa20')
'3020'
Оскільки в Python 3 filterповертає ітератор замість list, ви можете використовувати наступне:
>>> ''.join(filter(str.isdigit, 'aas30dsa20'))
'3020'
isdigit, генератор з isdigtзнаходиться на півдорозі між ними
rдля сирого рядка:re.sub(r"\D+", "", "aas30dsa20")
Ви можете використовувати фільтр:
filter(lambda x: x.isdigit(), "dasdasd2313dsa")
На python3.0 ви повинні приєднатися до цього (якось потворно :()
''.join(filter(lambda x: x.isdigit(), "dasdasd2313dsa"))
strщоб listпереконатися, що він працює як на py2, так і на py3:''.join(filter(lambda x: x.isdigit(), list("dasdasd2313dsa")))
по лінії відповіді байєра:
''.join(i for i in s if i.isdigit())
-це не цифра.
x.translate(None, string.digits)
видалить усі цифри з рядка. Щоб видалити літери та зберегти цифри, зробіть це:
x.translate(None, string.letters)
TypeError: translate () бере рівно один аргумент (2 наведено). Чому це питання було сприйнято в його нинішньому стані, досить неприємно.
У коментарях оп згадується, що він хоче зберегти десяткове місце. Це можна зробити за допомогою методу re.sub (відповідно до другої та найкращої відповіді IMHO), чітко вказавши символи, які слід зберегти, наприклад
>>> re.sub("[^0123456789\.]","","poo123.4and5fish")
'123.45'
Швидка версія для 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)
Ось порівняння продуктивності та регексу:
$ 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
Тож для мене це трохи більше, ніж у 3 рази швидше, ніж регулярний вираз. Це також швидше, ніж class Delвище, тому defaultdictщо всі його пошуки в C, а не (повільний) Python. Ось ця версія в моїй самій системі для порівняння.
$ python3.3 -mtimeit -s'import xx; x="aaa12333bb445bb54b5b52"' 'x.translate(xx.DD)'
100000 loops, best of 3: 13.6 usec per loop
Некрасиво, але працює:
>>> s
'aaa12333bb445bb54b5b52'
>>> a = ''.join(filter(lambda x : x.isdigit(), s))
>>> a
'1233344554552'
>>>
list(s)?
filter(lambda x: x.isdigit(), s)добре працював для мене. ... о, це тому, що я використовую Python 2.7.
$ python -mtimeit -s'import re; x="aaa12333bb445bb54b5b52"' 're.sub(r"\D", "", x)'
100000 петель, найкраще 3: 2,48 Usec на цикл
$ python -mtimeit -s'import re; x="aaa12333bab445bb54b5b52"' '"".join(re.findall("[a-z]+",x))'
100000 петель, найкраще 3: 2,02 Usec на петлю
$ python -mtimeit -s'import re; x="aaa12333bb445bb54b5b52"' 're.sub(r"\D", "", x)'
100000 петель, найкраще 3: 2,37 Usec на цикл
$ python -mtimeit -s'import re; x="aaa12333bab445bb54b5b52"' '"".join(re.findall("[a-z]+",x))'
100000 петель, найкраще 3: 1,97 Usec за петлю
Я зауважував, що приєднання швидше, ніж суб.
Ви можете прочитати кожного символу. Якщо вона цифра, то включіть її у відповідь. str.isdigit() Метод є способом дізнатися , чи є символ цифрою.
your_input = '12kjkh2nnk34l34'
your_output = ''.join(c for c in your_input if c.isdigit())
print(your_output) # '1223434'
Я цим користувався. 'letters'має містити всі листи, від яких ви хочете позбутися:
Output = Input.translate({ord(i): None for i in 'letters'}))
Приклад:
Input = "I would like 20 dollars for that suit"
Output = Input.translate({ord(i): None for i in 'abcdefghijklmnopqrstuvwxzy'}))
print(Output)
Вихід:
20