Фильтрация строк, содержащих только цифры и / или знаки препинания-python
мне нужно отфильтровать только строки, содержащие только цифры и / или фиксированный набор знаков препинания.
Я попытался проверить каждый символ, а затем суммировать логические условия, чтобы проверить, равен ли он len(str)
. Есть ли более подходящие для Python способ сделать это:
>>> import string
>>> x = ['12,523', '3.46', "this is not", "foo bar 42", "23fa"]
>>> [i for i in x if [True if j.isdigit() else False for j in i] ]
['12,523', '3.46', 'this is not', 'foo bar 42']
>>> [i for i in x if sum([True if j.isdigit() or j in string.punctuation else False for j in i]) == len(i)]
['12,523', '3.46']
2 ответов
используя all
с выражением генератора вам не нужно подсчитывать, сравнивать длину:
>>> [i for i in x if all(j.isdigit() or j in string.punctuation for j in i)]
['12,523', '3.46']
BTW, выше и код OP будет включать строки, содержащие только знаки препинания.
>>> x = [',,,', '...', '123', 'not number']
>>> [i for i in x if all(j.isdigit() or j in string.punctuation for j in i)]
[',,,', '...', '123']
чтобы справиться с этим, добавьте еще условие:
>>> [i for i in x if all(j.isdigit() or j in string.punctuation for j in i) and any(j.isdigit() for j in i)]
['123']
вы можете сделать это немного быстрее, сохранив результат строки.пунктуация в наборе.
>>> puncs = set(string.punctuation)
>>> [i for i in x if all(j.isdigit() or j in puncs for j in i) and any(j.isdigit() for j in i)]
['123']
для проверки этого можно использовать предварительно скомпилированное регулярное выражение.
import re, string
pattern = re.compile("[\d{}]+$".format(re.escape(string.punctuation)))
x = ['12,523', '3.46', "this is not", "foo bar 42", "23fa"]
print [item for item in x if pattern.match(item)]
выход
['12,523', '3.46']
небольшое сравнение времени, между решением @falsetru и моим
import re, string
punct = string.punctuation
pattern = re.compile("[\d{}]+$".format(re.escape(string.punctuation)))
x = ['12,523', '3.46', "this is not", "foo bar 42", "23fa"]
from timeit import timeit
print timeit("[item for item in x if pattern.match(item)]", "from __main__ import pattern, x")
print timeit("[i for i in x if all(j.isdigit() or j in punct for j in i)]", "from __main__ import x, punct")
выход на моей машине
2.03506183624
4.28856396675
таким образом, предварительно скомпилированный подход регулярных выражений в два раза быстрее, чем all
и any
подход.