Удалите все нечисловые символы (за исключением ".") из строки в Python



У меня есть довольно хороший рабочий фрагмент кода, но мне было интересно, есть ли у кого-нибудь лучшие предложения о том, как это сделать:



val = ''.join([c for c in val if c in '1234567890.'])


что бы вы сделали?

344   6  

6 ответов:

вы можете использовать регулярное выражение (используя re), чтобы сделать то же самое. Пример ниже соответствует запускам [^\d.] (любой символ, который не является десятичной цифрой или период) и заменяет их пустой строкой. Обратите внимание, что если шаблон компилируется с UNICODE флаг результирующая строка все еще может включать номера без ASCII. Кроме того, Результат после удаления "нечисловых" символов не обязательно является допустимым число.

>>> import re
>>> non_decimal = re.compile(r'[^\d.]+')
>>> non_decimal.sub('', '12.34fe4e')
'12.344'

еще один "питонический" подход

filter( lambda x: x in '0123456789.', s )

но регулярное выражение будет быстрее.

вот пример кода:

$ cat a.py
a = '27893jkasnf8u2qrtq2ntkjh8934yt8.298222rwagasjkijw'
for i in xrange(1000000):
    ''.join([c for c in a if c in '1234567890.'])

$ cat b.py
import re

non_decimal = re.compile(r'[^\d.]+')

a = '27893jkasnf8u2qrtq2ntkjh8934yt8.298222rwagasjkijw'
for i in xrange(1000000):
    non_decimal.sub('', a)

$ cat c.py
a = '27893jkasnf8u2qrtq2ntkjh8934yt8.298222rwagasjkijw'
for i in xrange(1000000):
    ''.join([c for c in a if c.isdigit() or c == '.'])

$ cat d.py
a = '27893jkasnf8u2qrtq2ntkjh8934yt8.298222rwagasjkijw'
for i in xrange(1000000):
    b = []
    for c in a:
        if c.isdigit() or c == '.': continue
        b.append(c)

    ''.join(b)

и результаты синхронизации:


$ time python a.py
real    0m24.735s
user    0m21.049s
sys     0m0.456s

$ time python b.py
real    0m10.775s
user    0m9.817s
sys     0m0.236s

$ time python c.py
real    0m38.255s
user    0m32.718s
sys     0m0.724s

$ time python d.py
real    0m46.040s
user    0m41.515s
sys     0m0.832s

похоже, что регулярное выражение является победителем до сих пор.

лично я нахожу регулярное выражение столь же читаемым, как и понимание списка. Если вы делаете это всего несколько раз, то вы, вероятно, получите больший удар по компиляции регулярного выражения. Делайте то, что jives с вашим кодом и стилем кодирования.

простое решение заключается в использовании регулярных expessions

import re 
re.sub("[^0-9^.]", "", data)
import string
filter(lambda c: c in string.digits + '.', s)

Если набор символов был больше, использование наборов, как показано ниже, может быть быстрее. Как бы то ни было, это немного медленнее, чем a.py.

dec = set('1234567890.')

a = '27893jkasnf8u2qrtq2ntkjh8934yt8.298222rwagasjkijw'
for i in xrange(1000000):
    ''.join(ch for ch in a if ch in dec)

по крайней мере, в моей системе вы можете сэкономить немного времени (и памяти, если ваша строка была достаточно длинной, чтобы иметь значение), используя выражение генератора вместо понимания списка в a.py:

a = '27893jkasnf8u2qrtq2ntkjh8934yt8.298222rwagasjkijw'
for i in xrange(1000000):
    ''.join(c for c in a if c in '1234567890.')

О, И вот самый быстрый способ, который я нашел на сегодняшний день на этой тестовой строке (намного быстрее, чем регулярное выражение), Если вы делаете это много, много раз и готовы мириться с накладными расходами на создание нескольких таблиц символов.

chrs = ''.join(chr(i) for i in xrange(256))
deletable = ''.join(ch for ch in chrs if ch not in '1234567890.')

a = '27893jkasnf8u2qrtq2ntkjh8934yt8.298222rwagasjkijw'
for i in xrange(1000000):
    a.translate(chrs, deletable)

В моей системе, которая работает в ~1.0 секунд, где регулярное выражение b.py работает в ~4,3 секунды.

Comments

    Ничего не найдено.