有关如何改善脚本的建议

时间:2019-02-01 06:22:24

标签: python python-3.x roman-numerals

能否请您提供有关此小型Python脚本的反馈。如果您可以提出更好的方法来完成从罗马数字到整数的转换,请告诉我。为了简单起见,没有错误处理。非常感谢。

#Script to convert Roman numeral to Integer.
#Note no error handling yet for simplicity.

def roman(mystring):
    roman_dict = {'I':'1',
                  'V':'5', 
                  'X':'10',
                  'L':'50',
                  'C':'100',
                  'D':'500',
                  'M':'1000'}
    x = roman_dict[mystring]
    return (x)

def get_myinput(myinput):
    sum = 0
    char_before = ''
    for char in myinput:
        if char_before  == '':
            subtract = 0
            pass
        elif char_before == 'I' and (char == 'V' or char == 'X'):
            subtract = 1
        elif char_before == 'X' and (char == 'L' or char == 'C'):
            subtract = 10
        elif char_before == 'C' and (char == 'D' or char == 'M'):
            subtract = 100
        else:
            subtract = 0
            pass

        converted = int(roman(char)) - subtract
        sum = sum + int(converted) - subtract
        char_before = char
    return (sum)

if __name__ == "__main__" :
    myinteger = get_myinput('MCMXCIV')
    print(myinteger)

1 个答案:

答案 0 :(得分:1)

欢迎来到SO。实际上,将其移至CodeReview的提示是正确的。但是,这项任务对我来说太有趣了,以至于不考虑如何开始,所以就在这里。
这个想法是先将罗马字母映射到'0'...'6',因此更容易判断当前值是否小于下一个。这是通过str.translate使用通过str.maketrans创建的初始定义的映射来完成的。
然后通过仅在末尾连接'0'进行比较,从而稍微简化了迭代过程,以便可以像中间的其他值一样处理最后一个值(并始终添加):

def roman2dec(rn_string):
    m = str.maketrans('IVXLCDM', '0123456')
    d = {'0':1, '1':5, '2':10, '3':50, '4':100, '5':500, '6':1000}

    rtran = rn_string.upper().translate(m)
    value = 0
    for i, c in enumerate(rtran):
        if rtran[i] < (rtran+'0')[i+1]:
            value = value - d[c]
        else:
            value = value + d[c]
    return(value)

str.upper()仅出于测试方便而插入...

一些测试:

roman2dec('MDCLXVI')
#1666
roman2dec('MCMXCIV')
#1994
roman2dec('xlii')
#42

编辑:
甚至可以简化为一个简短的功能:

def r2d(rn):
    d = {'I':1, 'V':5, 'X':10, 'L':50, 'C':100, 'D':500, 'M':1000}
    values = [d[c] for c in rn.upper()]
    signs = ([1, -1][a < b] for a, b in zip(values, values[1:]+[0]))
    return sum(a*b for a, b in zip(signs, values))

甚至

def r2d2(rn):
    d = {'I':1, 'V':5, 'X':10, 'L':50, 'C':100, 'D':500, 'M':1000}
    return sum(d[a] * [1, -1][d[a] < d[b]] for a, b in zip(rn.upper(), rn.upper()[1:]+'I'))

numpy方法:

def r2d_np(rn):
    import numpy as np
    d = {'I':1, 'V':5, 'X':10, 'L':50, 'C':100, 'D':500, 'M':1000}
    values = np.array([d[c] for c in rn.upper()])
    signs = np.append(np.where(np.diff(values)>0, -1, 1), 1)
    return sum(values*signs)