我有一个自由格式的持续时间字符串,其中包含小时和分钟值,其中之一可以是可选的
1 hour
12 hours 3 mins
47 mins
10 hours
1 min
我必须将它们转换为分钟数。首先搜索Python库,该库可以转换时间和持续时间,但字符串格式不允许使用这种方法
然后我尝试使用正则表达式提取数字组:
re.search("(\d+)?.*(\d+\w)", string).group(1)
re.search("(\d+)?.*(\d+\w)", string).group(2)
在存在小时和分钟值或仅存在分钟值的大多数情况下有效(因为我将第一组设为可选),当小时为一位数字(1小时)时,此正则表达式将失败。 同样因为我只提取没有描述性文字的数字组(小时和/或分钟),所以当只有小时值(带有两位数字)时,计算是错误的,例如10小时,并且错误地提取为第二组为分钟。
答案 0 :(得分:1)
您可以尝试使用 dateutil 和Regex
演示:
import dateutil.parser as dparser
import re
s = """1 hour
12 hours 3 mins
47 mins
10 hours
1 min"""
for line in s.splitlines():
print(dparser.parse(re.sub(r"(mins?)", "minutes", line), fuzzy=True).strftime("%H:%M:%S") )
输出:
01:00:00
12:03:00
00:47:00
10:00:00
00:01:00
答案 1 :(得分:0)
您可以将re.findall
与以下正则表达式配合使用:
import re
s = '''1 hour
12 hours 3 mins
47 mins
10 hours
1 min'''
for h, m in re.findall(r'(?=\d+ *hours?| *\d+ *min(?:ute)?s?)(?:(\d+) *hours?)?(?: *(\d+) *min(?:ute)?s?\b)?', s, flags=re.IGNORECASE):
print(int(h or 0) * 60 + int(m or 0))
这将输出:
60
723
47
600
1
答案 2 :(得分:0)
我写了这个简单的代码片段来解析您的所有情况。询问您是否有问题。
输出:
1 hour -> 1:00:00
12 hours 3 mins -> 12:03:00
47 mins -> 0:47:00
10 hours -> 10:00:00
1 min -> 0:01:00
random text -> 0:00:00
代码:
import re
from datetime import timedelta
number_word_regex = re.compile(r'(\d+) (\w+)')
def parse_fuzzy_duration(s):
ret = timedelta(0)
for number, word in number_word_regex.findall(s):
number = int(number)
if word in ['minute', 'min', 'minutes', 'mins']:
ret += timedelta(minutes=number)
elif word in ['hour', 'hours']:
ret += timedelta(hours=number)
return ret
for s in ['1 hour', '12 hours 3 mins', '47 mins', '10 hours', '1 min', 'random text']:
print(s, '->', parse_fuzzy_duration(s))
答案 3 :(得分:0)
其他答案很好,使用正则表达式的另一种方式(如果您确实愿意):
match = re.match(
r'((?P<hours>\d+) hours?)? ?((?P<mins>\d+) mins?)?',
'12 hours 3 mins'
)
match.groupdicts()
这样,可能使您更有意义(这是很多正则表达式工程的主要问题。我建议您尝试在{{3 }}进行一些测试和说明。