我必须解析具有已知结构的简单字符串列表,但我发现它不必要地笨重。 我觉得我错过了一个技巧,也许是一些简单的正则表达式会使这个变得微不足道?
字符串指的是将来某些年/月,我想把它变成十进制年。
通用格式:“aYbM”
如果a是年数,则b是这些可以是整数的月数,并且两者都是可选的(以及它们的标识符)
测试用例:
5Y3M == 5.25
5Y == 5.0
6M == 0.5
10Y11M = 10.91666..
3Y14M = raise ValueError("string '%s' cannot be parsed" %input_string)
到目前为止,我的尝试涉及字符串拆分,虽然它们确实产生了正确的结果但非常麻烦:
def parse_aYbM(maturity_code):
maturity = 0
if "Y" in maturity_code:
maturity += float(maturity_code.split("Y")[0])
if "M" in maturity_code:
maturity += float(maturity_code.split("Y")[1].split("M")[0]) / 12
return maturity
elif "M" in maturity_code:
return float(maturity_code[:-1]) / 12
else:
return 0
答案 0 :(得分:5)
您可以使用正则表达式
onSwipeOutAtEnd
表示
(?:(\d+)Y)?(?:(\d+)M)?
在
中使用时(?: start a non-grouping pattern
(\d+) match 1-or-more digits, grouped
Y followed by a literal Y
)? end the non-grouping pattern; matched 0-or-1 times
(?: start another non-grouping pattern
(\d+) match 1-or-more digits, grouped
M followed by a literal M
)? end the non-grouping pattern; matched 0-or-1 times
re.match(r'(?:(\d+)Y)?(?:(\d+)M)?', text).groups()
方法返回分组括号内的匹配部分。如果组不匹配,则返回groups()
。例如,
None
In [220]: re.match(r'(?:(\d+)Y)?(?:(\d+)M)?', '5Y3M').groups()
Out[220]: ('5', '3')
In [221]: re.match(r'(?:(\d+)Y)?(?:(\d+)M)?', '3M').groups()
Out[221]: (None, '3')
产量
import re
def parse_aYbM(text):
a, b = re.match(r'(?:(\d+)Y)?(?:(\d+)M)?', text).groups()
if a == b == None:
raise ValueError('input does not match aYbM')
a, b = [int(item) if item is not None else 0 for item in (a, b)]
return a + b/12.0
tests = [
('5Y3M', 5.25),
('5Y', 5.0),
('6M', 0.5),
('10Y11M', 10.917),
('3Y14M', 4.167),
]
for test, expected in tests:
result = parse_aYbM(test)
status = 'Failed'
if abs(result - expected) < 0.001:
status = 'Passed'
print('{}: {} --> {}'.format(status, test, result))
注意,如果Passed: 5Y3M --> 5.25
Passed: 5Y --> 5.0
Passed: 6M --> 0.5
Passed: 10Y11M --> 10.9166666667
Passed: 3Y14M --> 4.16666666667
的输入与模式不匹配,则不清楚会发生什么。使用上面的代码,不匹配会引发parse_aYbM
:
ValueError
但部分匹配可能会返回一个值:
In [227]: parse_aYbM('foo')
ValueError: input does not match aYbM
答案 1 :(得分:0)
您可以使用re.findall
>>> def parse(m):
s = 0
j = re.findall(r'\d+Y|\d+M', m)
for i in j:
if 'Y' in i:
s += float(i[:-1])
if 'M' in i:
s += float(i[:-1])/12
print(s)
>>> parse('5Y')
5.0
>>> parse('6M')
0.5
>>> parse('10Y11M')
10.916666666666666
>>> parse('3Y14M')
4.166666666666667
答案 2 :(得分:0)
不熟悉python正则表达式,但尝试类似的东西
(?<year>[^Y])\D(?<month>[^M]*)\D
可能就是这样做的。