У меня очень хороший рабочий код кода, но мне было интересно, есть ли у кого-нибудь лучшие предложения о том, как это сделать:
val = ''.join([c for c in val if c in '1234567890.'])
Что бы вы сделали?
У меня очень хороший рабочий код кода, но мне было интересно, есть ли у кого-нибудь лучшие предложения о том, как это сделать:
val = ''.join([c for c in val if c in '1234567890.'])
Что бы вы сделали?
Вы можете использовать регулярное выражение (используя re
модуль), чтобы выполнить одно и то же. Пример ниже соответствует прогонам [^\d.]
(любой символ, который не является десятичной цифрой или периодом) и заменяет их пустой строкой. Обратите внимание, что если шаблон скомпилирован с флагом UNICODE
, результирующая строка может по-прежнему включать не-ASCII-номера. Кроме того, результат после удаления "нечисловых" символов не обязательно является допустимым числом.
>>> import re
>>> non_decimal = re.compile(r'[^\d.]+')
>>> non_decimal.sub('', '12.34fe4e')
'12.344'
Вот пример кода:
$ 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
Похоже, что regex является победителем.
Лично я нахожу регулярное выражение так же легко читаемым, как и понимание списка. Если вы делаете это всего несколько раз, то, вероятно, вы будете больше поражать компиляцию регулярного выражения. Сделайте то, что jives с вашим кодом и стилем кодирования.
Другой "питонический" подход
filter( lambda x: x in '0123456789.', s )
но регулярное выражение выполняется быстрее.
Мое решение проще с использованием регулярного выражения:
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 секунды.