在正则表达式组上使用数学函数

时间:2013-08-11 20:59:39

标签: python regex

对于一个班级,我必须编写一个函数,该函数需要03:12:19(换句话说,3小时,12分钟和19秒)形式的时间并将它们转换为相应的秒数。我已经开始但似乎无法让数学工作,这是我现在的代码:

def secs(timestr):
    import re
    timexp = re.compile('(\d\d):(\d\d):(\d\d)')
    calc = re.sub(timexp,r'int(\1)*3600+int(\2*60)+int(\3)',timestr)
    return print(calc)

str = '03:20:13'
secs(str)

我已经搞乱了删除r,但它给了我一个奇怪的结果。帮助

3 个答案:

答案 0 :(得分:7)

正则表达式对于解析输入字符串可能有点过分,而且完全是用于计算总秒数的错误工具。这是一个简单的替代品:

def secs(timestr):
    hours, minutes, seconds = timestr.split(':')
    return int(hours) * 3600 + int(minutes) * 60 + int(seconds)

这不处理错误检查(不是正确数量的':'分隔符,非数字内容等),但是你的原始regexp方法也没有。如果你确实需要理智检查输入,我会这样做:

def secs(timestr):
    timeparts = timestr.split(':')
    if len(timeparts) == 3 and all((part.isdigit() for part in timeparts)):
        return int(timeparts[0]) * 3600 + int(timeparts[1] * 60 + int(timeparts[2])
    else:
        # not a matching string - do whatever you like.
        return None

还有其他方法。

如果你想要一个字符串而不是整数秒,return str(int(hours) * 3600 + int(minutes) * 60 + int(seconds))

编辑:响应“我被指示用正则表达式替换这样做,这就是我必须做的事情”:

re.sub可以采用两种不同的替换参数。您可以提供字符串模式或函数来计算替换字符串。字符串模式不进行数学运算,因此必须使用函数。

  

如果repl是一个函数,则会针对每个非重叠的模式调用它。该函数接受一个匹配对象参数,并返回替换字符串。

def _calculate_seconds(timematch):
    return str(int(timematch.group(1)) * 3600 + int(timematch.group(2)) * 60 + int(timematch.group(3)))

def secs(timestr):
    timexp = re.compile(r'(\d{1,2}):(\d{1,2}):(\d{1,2})')
    return re.sub(timexp, _calculate_seconds, timestr)

但这是一个糟糕的方法,除非你试图在一个更大的字符串中转换这些时间模式的多次出现。

在这里编译正则表达式并不是必需的甚至是有用的,因为每次调用函数时都要重做它。通常的方法是在函数外部编译它 - 但是regexp docs注意:

  

传递给re.match(),re.search()或re.compile()的最新模式的编译版本被缓存,因此一次只使用几个正则表达式的程序不必担心编译正则表达式。

但是,这是一个很好的习惯。只是不在这样的本地函数定义中。

答案 1 :(得分:1)

你正在使用re.sub,它将regex匹配替换为第二个参数。

相反,您应该运行re.match(timexp,timestr)来获取匹配对象。该对象有一个用于访问组的API(正则表达式的括号部分):match.group(0)是整个字符串,match.group(1)是第一个两位数的块,match.group(2)是第二,......

您可以从那里处理内存中的数字。

答案 2 :(得分:0)

另一种选择是尝试切片。 (以下是切片表示法的一些信息:Explain Python's slice notation

如果传递给函数的时间始终采用相同的格式(即hh:mm:ss),那么切片将允许您分离时间的每个分量。切片字符串仍会返回一个字符串,因此使用int()和每个切片时间组件。 secs函数看起来像这样:

def secs(timestr):
    hours = int(timestr[:2])
    minutes = int(timestr[3:5])
    seconds = int(timestr[6:])
    totalsecs = hours * 3600 + minutes * 60 + seconds
    return totalsecs