Форум сайта python.su
0
Нужно распарсить текстовый вид времени выполнения задачи в питоновское стандартное представление.
Сам не могу сходу написать регулярку и придумать алгоритм =( Мб кто-нибудь сталкивался с подобной задачей? гугление не помогло.
Все осложняется тем, что могут быть разные сложные варианты:
23d 5m
6h
25h 150m
и т.д.
Написать полностью не прошу, просто наставьте на путь истинный. Должно же быть красивое решение.
Офлайн
568
Конкретизируйте Ваши чаяния, то чего Вы хотите сейчас, понять не представляется возможным. Набор слов. Выражайтесь яснее, не стесняйтесь дать сообществу Вашу задачу более ширше - какие входные данные, что надо получить?
Офлайн
173
Как вариант:
import re import datetime _td_names = [ 'days', 'hours', 'minutes', 'seconds', ] td_regexps = {name : re.compile(r"(\d+)%s" % name[0]) for name in _td_names} def parse_timedelta(text): fields = {} for name, pattern in td_regexps.items(): m = pattern.search(text) if m: fields[name] = float(m.group(1)) if not fields: return None # or raise exception return datetime.timedelta(**fields) test_strings = [ "3d 5h 15m", "23d 5m", "6h", "25h 150m", "aasdf", ] for text in test_strings: print parse_timedelta(text)
import re import datetime _td_names = { 'd': 'days', 'h': 'hours', 'm': 'minutes', 's': 'seconds' } td_regexp = re.compile(r"\b(\d+)(%s)\b" % '|'.join(_td_names.keys())) def parse_timedelta(text): fields = {} for value, name in td_regexp.findall(text): fields[_td_names[name]] = float(value) if not fields: return None return datetime.timedelta(**fields) test_strings = [ "3d 5h 15m", "23d 5m", "6h", "25h 150m", "aasdf", ] for text in test_strings: print parse_timedelta(text)
Отредактировано reclosedev (Дек. 22, 2012 17:09:30)
Офлайн
568
reclosedev,
телепат 80-го левела!!!!!!!!!!
+1 восхищенье
Офлайн
173
FishHookНу не знаю
телепат 80-го левела!!!!!!!!!!
Вроде понятный вопрос.FishHookНапример, если из сплошного текста нужно timedelta выделить, мой вариант не подойдет.
какие входные данные,
Отредактировано reclosedev (Дек. 22, 2012 17:16:56)
Офлайн
857
>>> import re >>> >>> s = """ ... 23d 5m ... 6h ... 25h 150m ... 3d 5h 15m ... 23d 5m ... 6h ... 25h 150m ... aasdf ... """ >>> >>> pat = re.compile(r'((?P<day>\d+)d)?((?P<hour>\d+)h)?((?P<min>\d+)m)?') >>> >>> for line in s.splitlines(): ... mo = pat.match(line.replace(' ', '')) ... if mo is not None and mo.group(0): ... print(mo.group('day', 'hour', 'min')) ... ('23', None, '5') (None, '6', None) (None, '25', '150') ('3', '5', '15') ('23', None, '5') (None, '6', None) (None, '25', '150') >>>
Офлайн
173
py.user.next
Хороший вариант с именованными группами, только я бы их переименовал, чтобы с параметрами timedelta () совпадали.
pat = re.compile(r'((?P<days>\d+)d)?((?P<hours>\d+)h)?((?P<minutes>\d+)m)?') for line in s.splitlines(): mo = pat.match(line.replace(' ', '')) if mo is not None and mo.group(0): fields = {name: int(value) for name, value in mo.groupdict().items() if value is not None} print(datetime.timedelta(**fields))
Офлайн
857
reclosedevя так не делаю, потому что части остаются независимыми
только я бы их переименовал, чтобы с параметрами timedelta () совпадали
Отредактировано py.user.next (Дек. 24, 2012 12:34:21)
Офлайн
173
py.user.next
Звучит надуманно. Сомневаюсь что данный регексп будет использован за пределами одной функции, предназначение которой - парсинг timedelta. Хотя, может быть явная передача mo.group('days', ‘hours’, ‘minutes’) выглядела бы более читаемой.
Офлайн
857
reclosedevдело не в читаемости, у тебя одна часть кода зависит от другой
Хотя, может быть явная передача mo.group('days', ‘hours’, ‘minutes’) выглядела бы более читаемой.
reclosedevты даже не думаешь, что он может прийти из внешнего файла, в котором нигде не будет написано, что имена групп должны соответствовать datetime
Сомневаюсь что данный регексп будет использован за пределами одной функции
Офлайн