Видалення всіх нечислових символів із рядка в 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.