问题描述
我想动态地找到正确的序数根,例如:
111 = 111st
112 = 112nd
113 = 113rd ...
我尝试了其他解决方案,但找不到好的解决方案。
这是我的代码:
for number in range(1,114):
print(number)
ex1 = 11
ex2 = 12
ex3 = 13
if number == ex1:
print("is the " + str(number) + "th number.")
elif number % 10 == 1 or not ex1:
print("is the " + str(number) + "st number.")
elif number == ex2:
print("is the " + str(number) + "nd number.")
elif number % 10 == 2 or not ex2:
print("is the " + str(number) + "nd number.")
elif number == ex3:
print("is the " + str(number) + "rd number.")
elif number % 10 == 3 or not ex3:
print("is the " + str(number) + "rd number")
else:
print("is the " + str(number) + "th number.")
解决方法
请注意,11、12 和 13 具有 th 后缀。
另请注意,您可以更改 print
函数中的行尾(默认 \n
):
print('text',end=' ')
print('another text')
那么,我建议您使用 f"{data} constant text"
或 "{} constant text".format(data)
格式的字符串。
这是我对您的问题的解决方案:
def getSuffix(n):
if n < 0: raise Exception("Ordinal negative numbers are not allowed")
if n % 100 in [11,12,13]: return 'th'
if n % 10 == 1: return 'st'
if n % 10 == 2: return 'nd'
if n % 10 == 3: return 'rd'
return 'th'
for number in range(1,114):
print(f"{number} is the {number}{getSuffix(number)} number")
希望对您有所帮助。
,这是一个很好的解决方案:
ordinal = lambda n: "%d%s" % (n,"tsnrhtdd"[(n // 10 % 10 != 1) * (n % 10 < 4) * n % 10::4])
for number in range(1,114):
print(f'the {ordinal(number)} number. :) ')
为人类编辑
注意:变量名称不打算在生产环境中使用,我试图使其更加明确 lambda 函数的每个步骤的作用!
def get_ordinal(n):
hacking_string = "tsnrhtdd" # 1)
is_num_divisible_by_ten = (n // 10 % 10 != 1) # 2)
is_num_reminder_0_3= (n % 10 < 4) # 3)
are_both_false_or_both_true= is_num_divisible_by_ten * is_num_between_0_3 # 4)
get_index = are_both_false_or_both_true* n % 10 # 5)
return f'{number}{hacking_string[get_index::4]}' #6) ---> starts at t | s | n | r
for number in range(1,114):
print(f'the {get_ordinal(number)} number. :) ')
注意事项
找到的解决方案非常巧妙和聪明,我可能永远不会想到自己,正在使用一些聪明的数学技巧来找到数字的偏移量。 然而,根据要求,我简化了功能并添加了一些解释。
-
第一步。这个字符串最好看成这个"tsnr" "htdd" |在左侧是字符串的“根”,在右侧是末端。 (更多解释如下)
-
第 2 步。
is_num_divisible_by_ten
--> 使用 floor division 结果是 True 或 False。 -
第 3 步。
is_num_reminder_0_3
如果检查 N 和 10 的提醒是否在 0 和 3 之间,则返回 True/False 标志。 -
第 4 步。
are_both_false_or_both_true
是乘以 2 布尔值,在 Python 中 True 是 1,False 是 0,所以就像 do --> 1 * 0。只有当两者都存在时,变量才为 True值为 True 或两者均为 False,否则始终为 False。 -
第 5 步。
get_index
-> 返回 0 或 1 或 2 或 3。 -
第 6 步。这里的 hacky 部分,使用从 get_index 接收到的索引,使用 indexing-and-slicing 对
hacking_string
变量进行处理:
get_index 值始终是以下之一:“tsnr”和采取的步骤 (4) 这些“rhtdd”中的任何一个,因此可能的组合是:
get_index = 0 = "th"
get_index = 1 = "st"
get_index = 2 = "nd"
get_index = 3 = "rd"
终于
最好在 math.stackexchange 上询问其背后的确切数学,或者如果有人知道添加评论或编辑我的答案会很好!
参考文献(这不是我的解决方案)
指南
,因此,问题在于 111
显示为 111st
而不是 111th
。
你有 11
作为 ex1
,我假设是“例外 1”的缩写,但你的条件:
if number == ex1:
显然与 111
不匹配。
相反,您可以这样做:
if number % 100 == ex1:
这对于 11
、111
、211
等都适用
附注:
elif number % 10 == 1 or not ex1:
显然不是你想要的。这被解释为:
elif (number % 10 == 1) or (not ex1):
not ex1
不依赖于 number
,并且总是以相同的方式 (False
) 求值。但由于您已经单独检查 ex1
,因此在这里正确执行将是多余的。
如果您想更正该问题,以便无需检查 ex1
两次,您可以这样做:
if number % 10 == 1 and number % 100 != 11:
我认为在这种情况下使用 !=
比 not
更清晰,而且我认为将变量分配给 11
没有任何好处。
你可以这样做:
for number in range(1,114):
printedString = str(number)+' is the '+str(number)
if str(number) == '1' or (str(number)[-1] == '1' and str(number)[-2] != '1'):
printedString += 'st'
elif str(number) == '2' or (str(number)[-1] == '2' and str(number)[-2] != '1'):
printedString += 'nd'
elif str(number) == '3' or (str(number)[-1] == '3' and str(number)[-2] != '1'):
printedString += 'rd'
else:
printedString += 'th'
print(printedString+' number.')