对 int 到罗马数字的列表理解

List comprehension for int to roman numeral

我有一个函数 roman(x),它将 int (>= 1) 和 returns 罗马数字作为字符串。我已经实现了一个工作示例:

def roman(x: int) -> str:
    """Convert into to roman numeral"""
    
    L = [(1000, 'M'), (900, 'CM'), (500, 'D'), (400, 'CD'),
         (100, 'C'), (90, 'XC'), (50, 'L'), (40, 'XL'),
         (10, 'X'), (9, 'IX'), (5, 'V'), (4, 'IV'), (1, 'I')]

    y = ""
    for val, sym in L:
        y += sym*(x//val)
        x -= val*(x//val)

    return y
>>> roman(399)
'CCCXCIX'

我问的是如何转换for循环:

y = ""
for val, sym in L:
    y += sym*(x//val)
    x -= val*(x//val)

return y

进入列表理解

return "".join([ ... ])

L 不需要嵌入到列表理解中,可以保持原样。这样函数就是这样的形式:

def roman(x: int) -> str:
    """Convert into to roman numeral"""

    L = [(1000, 'M'), (900, 'CM'), (500, 'D'), (400, 'CD'),
         (100, 'C'), (90, 'XC'), (50, 'L'), (40, 'XL'),
         (10, 'X'), (9, 'IX'), (5, 'V'), (4, 'IV'), (1, 'I')]

    # Return list comprehension as a string
    return "".join([ ... ])

版本使用functools.reduce

from functools import reduce

def roman(x: int) -> str:
    """Convert into to roman numeral"""

    L = [(1000, 'M'), (900, 'CM'), (500, 'D'), (400, 'CD'),
         (100, 'C'), (90, 'XC'), (50, 'L'), (40, 'XL'),
         (10, 'X'), (9, 'IX'), (5, 'V'), (4, 'IV'), (1, 'I')]

    return reduce(lambda s, c: (s[0] + c[1]*(s[1]//c[0]), s[1] - c[0]*(s[1]//c[0])), L, ("", x))[0]

print(roman(399)) # CCCXCIX

可怕,不可读。不要使用它

如果您不介意递归,这实际上是一个非常好的用例。

L = [(1000, 'M'), (900, 'CM'), (500, 'D'), (400, 'CD'),
 (100, 'C'), (90, 'XC'), (50, 'L'), (40, 'XL'),
 (10, 'X'), (9, 'IX'), (5, 'V'), (4, 'IV'), (1, 'I')]

def roman(num):
  if num == 0: # Base case: when we reach zero, return empty string
    return ''
  # Recursive step: iterate over values and their characters
  for v, n in L:
    if num >= v: # If their difference is positive, we recurse
      return n + roman(num - v) # We append the result to the numeral

roman(399)
>> 'CCCXCIX'
def roman(x: int) -> str:
    """Convert into to roman numeral"""

    L = [(1000, 'M'), (900, 'CM'), (500, 'D'), (400, 'CD'),
         (100, 'C'), (90, 'XC'), (50, 'L'), (40, 'XL'),
         (10, 'X'), (9, 'IX'), (5, 'V'), (4, 'IV'), (1, 'I')]

    return ''.join([(sym*(x//val), (x:=x-val*(x//val)))[0] for val, sym in L])


print(roman(399))  # CCCXCIX