添加时间列表的 Pythonic 方式

Pythonic way to add a list of time

我有一个包含日期和时间列表(字符串形式)的字典。

input = {
    '2016-02-11': [
        u'30m',
        u'2h 30m',
        u'1h',
        u'2h',
        u'30m',
        u'1h',
        u'30m',
        u'1h',
        u'45m'
    ],
    '2016-01-27': [
        u'1d'
    ],
    '2016-01-28': [
        u'30m',
        u'5h',
        u'30m',
        u'1h',
        u'45m'
    ],
    '2016-01-29': [
        u'30m',
        u'6h 30m',
        u'45m'
    ],
    '2016-02-09': [
        u'30m',
        u'15m',
        u'4h',
        u'15m',
        u'2h',
        u'45m'
    ]
}

如何在列表中每次添加?这样新字典看起来像这样:

output = {
    '2016-02-11': [
        '9h 45m'
    ],
    '2016-01-27': [
        '8h'
    ],
    '2016-01-28': [
        '7h 45m'
    ],
    '2016-01-29': [
        '7h 45m'
    ],
    '2016-02-09': [
        '7h 45m'
    ]
}

一些注意事项:

创建辅助函数,将 1h 30m 之类的字符串转换为 90(表示 90 分钟),并反转函数:

def parse_time(s):
    """ '1h 30m' -> 90 """
    m = 0
    for x in s.split():
        if x.endswith('d'):
            m += int(x[:-1]) * 60 * 8  # NOTE: 8, not 24
        elif x.endswith('h'):
            m += int(x[:-1]) * 60
        elif x.endswith('m'):
            m += int(x[:-1])
    return m

def to_time(m):
    """ 90 -> '1h 30m' """
    d, m = divmod(m, 60 * 8)  # NOTE: 8, not 24
    h, m = divmod(m, 60)
    ret = []
    if d:
        ret.append('{}d'.format(d))
    if h:
        ret.append('{}h'.format(h))
    if m:
        ret.append('{}m'.format(m))
    return ' '.join(ret) or '0m'

用法:将时间字符串转换为 int 值(分钟),并对这些值求和,将分钟转换回时间字符串:

>>> parse_time('1h 30m')
90
>>> to_time(90)
'1h 30m'
>>> to_time(parse_time('1h 30m') + parse_time('30m'))
'2h'

>>> times = {
...     '2016-02-11': [ u'30m', u'2h 30m', u'1h', u'2h', u'30m',
...                     u'1h', u'30m', u'1h', u'45m' ],
...     '2016-01-27': [ u'1d' ],
...     '2016-01-28': [ u'30m', u'5h', u'30m', u'1h', u'45m' ],
...     '2016-01-29': [ u'30m', u'6h 30m', u'45m' ],
...     '2016-02-09': [ u'30m', u'15m', u'4h', u'15m', u'2h', u'45m' ]
... }
>>> {d: to_time(sum(map(parse_time, ts))) for d, ts in times.items()}
{'2016-01-27': '1d',
 '2016-01-28': '7h 45m',
 '2016-01-29': '7h 45m',
 '2016-02-09': '7h 45m',
 '2016-02-11': '1d 1h 45m'}

如果您需要日期字符串来列出:

>>> {d: [to_time(sum(map(parse_time, ts)))] for d, ts in times.items()}
{'2016-01-27': ['1d'],
 '2016-01-28': ['7h 45m'],
 '2016-01-29': ['7h 45m'],
 '2016-02-09': ['7h 45m'],
 '2016-02-11': ['1d 1h 45m']}

这是我的做法(虽然不是很pythonic):

def time_to_string(d, h, m):
    total = d*8*60 + h*60 + m
    d = int(total / (8 * 60))
    h = int((total - d*8*60)/60)
    m = total - d*8*60 - h*60
    s = []
    if d != 0:
        h += d * 8
    if h != 0:
        s.append('{}h'.format(h))
    if m != 0:
        s.append('{}m'.format(m))
    return ' '.join(s)

for k, day in inputs.items():
    total = 0
    dtot, htot, mtot = 0, 0, 0
    for times in day:
        parts = times.split()
        d, h, m = 0, 0, 0
        for p in parts:
            if p.endswith('d'):
                d = int(p[:-1])
            elif p.endswith('h'):
                h = int(p[:-1])
            elif p.endswith('m'):
                m = int(p[:-1])
        dtot += d
        htot += h
        mtot += m
    inputs[k] = time_to_string(dtot, htot, mtot)

for k, val in inputs.items():
    print(k, val)