我有以下字符串:
str = "MMX Lions Television Inc"
我需要将其转换为:
conv_str = "2010 Lions Television Inc"
我有以下函数将罗马数字转换为等价的整数:
numeral_map = zip(
(1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1),
('M', 'CM', 'D', 'CD', 'C', 'XC', 'L', 'XL', 'X', 'IX', 'V', 'IV', 'I')
)
def roman_to_int(n):
n = unicode(n).upper()
i = result = 0
for integer, numeral in numeral_map:
while n[i:i + len(numeral)] == numeral:
result += integer
i += len(numeral)
return result
我如何使用re.sub
来获取正确的字符串?
(注意:我尝试使用此处描述的regex
:How do you match only valid roman numerals with a regular expression?但它无效。)
答案 0 :(得分:6)
在寻找常用功能/库时,请务必尝试Python Package Index。
这是list of modules related to the keyword 'roman'。
例如,'romanclass'有一个实现转换的类,引用文档:
So a programmer can say:
>>> import romanclass as roman
>>> two = roman.Roman(2)
>>> five = roman.Roman('V')
>>> print (two+five)
and the computer will print:
VII
答案 1 :(得分:2)
re.sub()
可以接受一个函数作为替换函数,该函数将接收一个参数,即Match对象,并且应该返回一个替换字符串。您已经有了将罗马数字字符串转换为int的功能,因此这并不困难。
在你的情况下,你会想要一个像这样的函数:
def roman_to_int_repl(match):
return str(roman_to_int(match.group(0)))
现在您可以修改您链接的问题中的正则表达式,以便在更大的字符串中找到匹配项:
s = "MMX Lions Television Inc"
regex = re.compile(r'\b(?=[MDCLXVI]+\b)M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})\b')
print regex.sub(roman_to_int_repl, s)
这是正则表达式的一个版本,它不会替换字符串中的“LLC”:
regex = re.compile(r'\b(?!LLC)(?=[MDCLXVI]+\b)M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})\b')
您还可以使用带有修改替换功能的原始正则表达式:
def roman_to_int_repl(match):
exclude = set(["LLC"]) # add any other strings you don't want to replace
if match.group(0) in exclude:
return match.group(0)
return str(roman_to_int(match.group(0)))