ice
Июнь 25, 2008 12:09:37
Доброго времени суток.
Есть функция и параметр, который нужно проверить на валидность.
1: это должна быть строка
2: строка должна быть из 2 или больше символов
3: Символы должны быть строго из списка (для каждой позиции свой список)
Вопрос: как всю эту проверку сделать быстро и красиво? if (.. and .. and) как-то сильно ущербно смотрится ..
как вариант составил все возможные варианты строки в другой список и проверяю if (… in …) но это сильно долго так как список получился не маленький.
Кто-нить сталкивался с такой задачей?
Ferroman
Июнь 25, 2008 13:54:12
1. Регулярные выражения
2. Цикл + брейк если символ в позиции not in
- Регулярными - будет быстрее и надёжнее ИМХО.
ice
Июнь 25, 2008 14:01:55
А как это описать регулярными выражениями? я с циклом сейчас как раз и сделал, но просто интересно как это описать…
например в первой позиции у меня лист из 13 символов
во второй из 4
в третьей, если есть - из 40
и тд. до 6. После 6 допускаются только символы из 6 списка.
Причем там не только буквы, но и цифры и символы специальные.
что-то я даже близко не представляю как это на re сделать.
bialix
Июнь 25, 2008 14:26:45
на re проверка попадния символа в диапазон делается через '' синтаксис.
Имхо тебе лучше проверка посимвольно
if s in ('a', ‘x’, ‘c’, …)
Ferroman
Июнь 25, 2008 14:30:11
Сделай не все сразу, а по-частям. Будет понятнее.
Например проверка, соответсвует ли первый символ одному из “abvged” а второй (если не конец строки) “12345”.
import re
print re.compile("^([abvgde])([12345]|$)").match("aw") # ok
print re.compile("^([abvgde])([12345]|$)").match("b") # ok
print re.compile("^([abvgde])([12345]|$)").match("w") # None
print re.compile("^([abvgde])([12345]|$)").match("w1") # None
print re.compile("^([abvgde])([12345]|$)").match("g3") # ok
Вернёт None если строка не соответствует или MatchObject если все “ок”
Ferroman
Июнь 25, 2008 14:31:41
Имхо тебе лучше проверка посимвольно
А почему?
Хе хе хе 666 пост bialix'а :)
ice
Июнь 25, 2008 15:01:35
bialix
Имхо тебе лучше проверка посимвольно
if s in ('a', ‘x’, ‘c’, …)
вот как раз так и работает сейчас.
try:
for i in range(len(str)): # у меня 3000 питон, там нет xrange
# тут еще проверка на 6 позицию
……
if str
in main_list:
…..
except (….):
….
думаю на этом и остановится. процедура не частая, только в конструкторе, потом идет работа уже исходя из того, что строка правильная и уже все раскидано по позициям.
с re тоже попробую, пригодится.
ZAN
Июнь 25, 2008 15:44:44
Регулярные выражения - намного мощнее, чем что бы там ни было, но, учитывая простоту задачи, можно обойтись без них.
Сложность, фактически, скорее не в реализации, а в задании конфигурации для валидной строки.
Один из вариантов:
import warnings
'''список ниже - конфигураци для валидности строки.
Нулевой позиции соответстует набор символов ‘abc’, второй позиции - ‘abcd’ и т.д.'''
validityList =
def check(validityList, myString):
for index, char in enumerate(myString):
‘'’проверка на валидность посимвольно'''
if char not in validityList:
warnings.warn('invalid char “%s” in position %s' %(char, index))
ice
Июнь 26, 2008 09:14:27
ZAN, этот вариант мне нравится больше :)
И ведь забыл я совсем про енумирейт
def check(validityList, myString):
try:
for index, char in enumerate(myString):
'''проверка на валидность посимвольно'''
j = min (index, 5)
if char not in validityList[j]:
warnings.warn('invalid char "%s" in position %s' %(char, index))
else:
if index < 1:
warnings.warn('invalid string')
except (..): # TypeError, NameError
...
Вот что-то типа такого и получилось :)
PyCraft
Июнь 26, 2008 12:49:27
бррррр
ИМХО, регулярка и только регулярка т.к. намного быстрее и намного нагляднее и понятнее
import re
#Назначаем допустимые символы для каждой позиции, можно использовать диапазоны и регулярные выражения
s1="qwer1"
s2="tyui2"
s3="op3"
s4="asdfghjkl4"
s5="zxcvb5"
s6="nm6"
#Компилируем регулярное выражение с предварительным форматированием
rec=re.compile("^([%s])([%s])($|[%s])($|[%s])($|[%s])($|[%s]*)$" % (s1,s2,s3,s4,s5,s6))
#^ - Начало строки
#()- атомарное выражение - символ
#$ - Конец строки
#| - ИЛИ
#[]- список символов применимых в данной позиции
#* - любое количество повторов
#Всего 6 правил, шестое распространяется на все последующие символы до конца строки
#Применяем
print rec.match("q") #None - меньше двух символов
print rec.match("qt") #OK
print rec.match("qto") #OK
print rec.match("qtto") #None - 3символ не входит в список
print rec.match("q6o") #None - 2символ не входит в список
print rec.match("qo") #None - пропустили 2символ и теперь 'o' не входит в список
print rec.match("qto4") #OK
print rec.match("12345") #OK
print rec.match("123456n6m6n") #OK