Удаление всех нечисловых символов из строки в Python

Ответы:

285
>>> import re
>>> re.sub("[^0-9]", "", "sdkjh987978asd098as0980a98sd")
'987978098098098'
Нед Батчелдер
источник
93
это может быть re.sub (r "\ D", "", "sdkjh987978asd098as0980a98sd")
newacct
3
и это могло быть: from re import sub
Джеймс Косс
95

Не уверен, что это наиболее эффективный способ, но:

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

В ''.joinозначает часть , чтобы объединить все полученные символы вместе без каких - либо символов между ними. Затем остальная часть - это понимание списка, где (как вы, наверное, догадались) мы берем только те части строки, которые соответствуют условию isdigit.

Марк Рушаков
источник
1
Это наоборот. Я думаю, вы имеете в виду «не c.isdigit ()»
Райан Р. Росарио
8
Удалите все нечисловые == оставьте только числовые.
Марк Рушаков, 08
11
Мне нравится, что этот подход не требует повторного использования для этой простой функции.
триуненатура
Обратите внимание, что в отличие от реализаций, использующих str.translate, это решение работает как в python 2.7, так и в 3.4. Спасибо!
Alex
1
Я предпочитаю эту альтернативу. Мне кажется, что использование регулярного выражения излишне.
alfredocambera
20

Это должно работать как для строк, так и для объектов Unicode в Python2, а также для строк и байтов в 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

Чтобы добавить еще одну опцию к этому миксу, в stringмодуле есть несколько полезных констант . Хотя они более полезны в других случаях, их можно использовать здесь.

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

В модуле есть несколько констант, в том числе:

  • ascii_letters (abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ)
  • hexdigits (0123456789abcdefABCDEF)

Если вы интенсивно используете эти константы, может быть стоит скрыть их в frozenset. Это позволяет выполнять поиск O (1), а не O (n), где n - длина константы для исходных строк.

>>> digits = frozenset(digits)
>>> ''.join(c for c in "abc123def456" if c in digits)
'123456'
Тим Макнамара
источник
'' .join (c вместо c в "abc123def456", если c.isdigit ()) работает в моем python 3.4
Эйно Мякитало
8

@Ned Batchelder и @newacct дали правильный ответ, но ...

На всякий случай, если в вашей строке есть запятая (,) десятичная (.):

import re
re.sub("[^\d\.]", "", "$1,999,888.77")
'1999888.77'
кенют
источник
5

Самый быстрый подход, если вам нужно выполнить больше, чем одну или две таких операции удаления (или даже одну, но с очень длинной строкой! -), - это полагаться на translateметод строк, даже если для этого требуется некоторая подготовка:

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

Этот translateметод отличается, и, возможно, немного проще в использовании для строк Unicode, чем для байтовых строк, кстати:

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

Возможно, вы захотите использовать класс сопоставления, а не фактический dict, особенно если ваша строка Unicode может потенциально содержать символы с очень высокими значениями ord (что сделало бы dict слишком большим ;-). Например:

>>> 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) Не программируйте магические числа жестко; s / 65536 / sys.maxunicode / (2) dict безусловно "чрезмерно большой", потому что вход "потенциально может" содержать (sys.maxunicode - number_of_non_numeric_chars)записи. (3) подумайте, может ли string.digits быть достаточным, что приведет к необходимости взломать модуль unicodedata (4) рассмотреть re.sub (r '(? U) \ D +', u '', text) для простоты и потенциала скорость.
Джон Мачин,
2

Многие правильные ответы, но если вы хотите, чтобы он был с плавающей точкой, напрямую, без использования регулярного выражения:

x= '$123.45M'

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

123,45

Вы можете изменить точку для запятой в зависимости от ваших потребностей.

измените это, если вы знаете, что ваше число является целым числом

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

1123

Альберто Ибарра
источник