Как я могу удалить все символы, кроме чисел, из строки?
Как я могу удалить все символы, кроме чисел, из строки?
Ответы:
В 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
метод стоит знать и использовать. Другой популярный не-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
на 50% медленнее, чем RE, поэтому .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 мксек на цикл
$ python -mtimeit -s'import re; x="aaa12333bab445bb54b5b52"' '"".join(re.findall("[a-z]+",x))'
100000 циклов, лучшее из 3: 2,02 пользователя на цикл
$ python -mtimeit -s'import re; x="aaa12333bb445bb54b5b52"' 're.sub(r"\D", "", x)'
100000 циклов, лучше всего 3: 2,37 циклов на цикл
$ python -mtimeit -s'import re; x="aaa12333bab445bb54b5b52"' '"".join(re.findall("[a-z]+",x))'
100000 циклов, лучшее из 3: 1,97 циклов за цикл
Я заметил, что соединение быстрее, чем саб.
Вы можете прочитать каждый символ. Если это цифра, то включите ее в ответ. str.isdigit()
Метод является способом узнать , является ли символ цифрой.
your_input = '12kjkh2nnk34l34'
your_output = ''.join(c for c in your_input if c.isdigit())
print(your_output) # '1223434'
Не один лайнер, но очень просто:
buffer = ""
some_str = "aas30dsa20"
for char in some_str:
if not char.isdigit():
buffer += char
print( buffer )
Я использовал это. '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