我有一个看起来像下面的列表;
timeLength = ["1h", " 2h 1min", " 1h 37min", "1h 33min",''''']
我要做的是将所有这些转换为整数分钟。 我设法进行了尝试,但例外情况适用于“ 2h 1min”,如果h没有出现给您错误,则只能使用min。
try:
hour, minute = timeLength.split("h")
hour = (int(hour)* 60)
minString = minute.strip("min")
minString = re.findall(r'\d+', minString)
minString = list(map(int, minString))
minString = minString[0]
totalLength = minString + hour
except:
hour = 0
minString = timeLength.strip("min")
minString = re.findall(r'\d+', minString)
minString = list(map(int, minString))
minString = minString[0]
totalLength = hour + minString
print(totalLength)
要考虑只有“ h”的实例,我需要添加些什么。
注意:我可能还没有发现更多实例,所以我需要一种在它们出现时轻松添加它们的方法。
谢谢。
答案 0 :(得分:3)
我个人将使用单个正则表达式解决此问题,而不是尝试分别枚举所有可能的格式:
import re
def to_minutes(s):
h, m = re.match(r'(?:(\d+)h)?\s*(?:(\d+)min)?', s.strip()).groups()
return int(h or 0) * 60 + int(m or 0)
timeLength = ["1h", " 2h 1min", " 1h 37min", "1h 33min"]
for s in timeLength:
print(s, to_minutes(s))
这里:
(?:(\d+)h)?
可选地匹配一个数字,后跟h
; \s*
匹配零个或多个空格; (?:(\d+)min)?
可选地匹配数字,其后跟min
。 (\d+)
捕获数字,而周围的(?:)?
只是在不创建捕获组的情况下使某些内容可选的一种方式。
最后,h or 0
和m or 0
只需将None
(如果输入中不存在小时或分钟,则用零替换)就可以简化计算。
很容易将此方案扩展为更多的时间单位(天,周等)。
请注意,如果我在生产代码中执行此操作,则将正则表达式的格式设置为re.VERBOSE
with inline comments。
答案 1 :(得分:2)
只要我们使用正则表达式,不妨充分利用它:
def to_minutes(text):
match = re.match('\s*(\d+)h(?:\s*(\d+)m)?', timelength)
if match is None:
# it wasn't a valid string, so handle the error as you like
else:
h, m = match.groups()
# the `m` may be None, but otherwise both values are valid for `int`.
if m is None:
m = 0
return int(h) * 60 + int(m)
破坏正则表达式:
\s*(\d+)h(?:\s*(\d+)m)?
^^^
zero or more whitespace chars
^^^^^^
digits followed by 'h' (captured)
^^^ ^^
optionally this stuff, but don't make a capturing group
^^^
whitespace again
^^^^^^
digits followed by 'm' (captured)
然后,每个成功的比赛都有小时和分钟计数的分组。当分钟计数组(由包裹的(?:...)?
设为可选)不匹配时,该组将捕获None
而不是子字符串。非捕获组使我们可以指定最后一个?
的可选内容,而无需使另一个捕获m
和前导空白的组成为可能。