Видалення всіх нечислових символів із рядка в Python


Відповіді:



90

Не впевнений, чи це найбільш ефективний спосіб, але:

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

В ''.joinозначає частину , щоб об'єднати всі отримані символи разом без будь - яких символів між ними. Тоді решта - це розуміння списку, де (як ви, напевно, здогадуєтесь) ми беремо лише ті частини рядка, які відповідають умові isdigit.


1
Це робить навпаки. Я думаю, ти маєш на увазі "не c.isdigit ()"
Ryan R. Rosario

7
Видаліть усі нечислові == тримайте лише числові.
Марк Рушакофф

10
Мені подобається, що для цієї простої функції цей підхід не потребує повторного використання.
триєдиність

Зауважте, що на відміну від реалізацій, що використовують str.translate, це рішення працює як в python 2.7, так і в 3.4. Дякую!
Алекс

1
Я віддаю перевагу цій альтернативі. Використання регулярного вираження мені здається непосильним.
alfredocambera

18

Це має працювати як для об'єктів, так і для об'єктів 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 ()) працює в моєму пітоні 3.4
Eino Mäkitalo

7

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

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

>>> 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) Дикт безумовно "надмірно великий", оскільки вхід "потенційно" може містити (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 рік

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.