Подтвердить что ты не робот

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

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

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

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

4b9b3361

Ответ 1

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

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

Ответ 2

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

$ 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 с вашим кодом и стилем кодирования.

Ответ 3

Другой "питонический" подход

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

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

Ответ 4

Мое решение проще с использованием регулярного выражения:

import re 
re.sub("[^0-9^.]", "", data)

Ответ 5

import string
filter(lambda c: c in string.digits + '.', s)

Ответ 6

Если набор символов был больше, использование наборов, как показано ниже, может быть быстрее. Как бы то ни было, это немного медленнее, чем 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 секунды.