Разбор странно отформатированного выражения времени из строки - PullRequest
0 голосов
/ 13 февраля 2019

Я пытаюсь разобрать отформатированную строку.Мне нужно знать, сколько часов, минут и секунд работал каждый извлеченный мной проект.

Данные, которые я получаю, представлены в следующем формате, например:

PT5H12M3S, это означает 5 часов 12минут 3 секунды.

Однако, если время работы меньше часа, оно просто не будет отображаться:

PT12M3S, это означает 12 минут 3 секунды.

Более того, если над проектом не работали (или только в течение менее минуты), данные будут отображаться следующим образом:

PT0S

Если в проекте отработано только полные часына нем это будет отображаться как:

PT5H

Я попытался проанализировать данные с помощью следующего кода:

estimated = track_data['project']['estimate']['estimate'].split('PT')[1]
estimated_hours = estimated.split('H')[0]
estimated_minutes = estimated_hours.split('M')[0]
estimated_seconds = estimated_minutes.split('S')[0]

, но это решение работает, только если данныев формате PT5H12M3S.Во всех других форматах это идет не так.Если я, например, получу данные PT5H, то предполагаемые часы будут равны 5, но также предполагаемые минуты и секунды также будут равны 5.Очевидно, что это не то, что мы хотим.

Есть ли кто-нибудь, кто может дать мне руководство о том, где искать?Я пробовал некоторые другие вещи с split, но, похоже, он не работает, потому что если он не может найти 'M' или 'S', он просто будет повторять одно и то же число.

Надеюсь, что это имеет смысл и спасибозаранее.

Ответы [ 5 ]

0 голосов
/ 13 февраля 2019

Надеюсь, этот код имеет смысл.Это очень простой подход, при котором вы перебираете символы строки, добавляя цифры к текущему и оценивая их при достижении буквенного символа ('S', 'M', 'H').

estimated = 'PT5H'
clean = estimated.split('PT')[1]
seconds = 0
minutes = 0
hours = 0
current = ''

for char in clean:
    if char.isdigit():
        current += char
    else:
        if char == 'S':
            seconds = int(current)
        elif char == 'M':
            minutes = int(current)
        else:
            hours = int(current)

        current = ''

print(hours, minutes, seconds)
0 голосов
/ 13 февраля 2019

Решение без регулярных выражений, основанное на условных выражениях

def parse_time(str_to_parse):
    str_to_parse = str_to_parse.split('PT')[1]
    time_units = ['H', 'M', 'S'] #this needs to always be in left to right or bigger to smaller order
    estimated_time = {k: 0 for k in time_units} 
    for k in time_units:
        if k in str_to_parse:
            left, right = str_to_parse.split(k)
            estimated_time[k], str_to_parse = int(left), right
    return estimated_time

estimated = "PT12M3S"
final_time = parse_time(estimated)
print(final_time)
{'H': 0, 'M': 12, 'S': 3}
0 голосов
/ 13 февраля 2019

Для этого вы можете использовать регулярные выражения:

import re

PROJECT_TIME_REGEX = re.compile(r'PT(?:(\d+)H)?(?:(\d+)M)?(?:(\d+)S)?')

def get_project_time(s):
    m = PROJECT_TIME_REGEX.match(s)
    if not m:
        raise ValueError('invalid string')
    hour, min, sec = (int(g) if g is not None else 0 for g in m.groups())
    return hour, min, sec

print(get_project_time('PT5H12M3S'))
# (5, 12, 3)
print(get_project_time('PT12M3S'))
# (0, 12, 3)
print(get_project_time('PT0S'))
# (0, 0, 0)
print(get_project_time('PT5H'))
# (5, 0, 0)
0 голосов
/ 13 февраля 2019

Как это?

import re

def parsept(ptstring):
    regex = re.compile(
            r'PT'
            r'(?:(?P<h>\d+)H)?'
            r'(?:(?P<m>\d+)M)?'
            r'(?:(?P<s>\d+)S)?')
    m = regex.match(ptstring)
    if m:
        return (int(m.group('h')) if m.group('h') else 0, 
            int(m.group('m') if m.group('m') else 0,
            int(m.group('s') if m.group('s') else 0)
    # else
    raise ValueError('{0} does not look like a valid PTxHyMzS string'.format(ptstring))
0 голосов
/ 13 февраля 2019

Вы можете использовать регулярные выражения и группы в регулярном выражении для захвата часов, минут и секунд - все это может быть необязательным.

Что-то вроде: /PT(\d*)H?(\d*)M?(\d*)S?/

скобки захватывают группы.Таким образом, ваши группы захвата будут содержать часы, минуты и секунды (все из которых являются необязательными).

Но регулярные выражения не так удобочитаемы.Я настоятельно рекомендую попробовать библиотеки комбинатора парсера, такие как Parsec .Комбинаторы парсеров гораздо более читабельны и удобны в обслуживании, и писать их очень приятно.

...