【问题标题】:Find ordinal numbers with loop dynamically: find th - st - nd - rd使用循环动态查找序数:find th - st - nd - rd
【发布时间】:2021-04-07 01:14:34
【问题描述】:

例如,我想动态找到正确的序数根:

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.")

【问题讨论】:

  • 我真的不明白你想要完成什么。是不是只想“1是第1个数字”“2是第2个数字”……“114是第114个数字”?
  • 它似乎运行良好 - 它确实输出了预期的格式化数字。那么你的问题是什么?
  • 这不是 for 循环的问题;这是循环内部逻辑的问题。请阅读how to debug small programs 并尝试诊断逻辑错误的地方。特别是,检查哪些数字给出了错误的结果,并尝试使用这些值跟踪您的逻辑。
  • 所以基本上你是在尝试打印给定范围内的基数,并且正在寻找一种更短的方法来做到这一点?
  • 嗯,那是因为条件111 == 11 不是True :) 你可能需要找到一种方法来测试一个数字是否以异常结尾,而不仅仅是等于它

标签: python python-3.x loops for-loop ordinal


【解决方案1】:

这是一个很好的解决方案:

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. :) ')

注意事项

找到的解决方案非常哈克和聪明,我可能永远不会自己想出来,正在使用一些聪明的数学技巧来找到数字的偏移量。 然而,根据要求,我简化了函数并添加了一些解释。

  • 第 1 步。这个字符串最好看成这个 "tsnr" "htdd" |左边是字符串的“根”,右边是末端。 (下面有更多解释)

  • 第 2 步。is_num_divisible_by_ten --> 使用 floor division 结果为真或假。

  • Step 3.is_num_reminder_0_3如果检查N和10的提醒是否在0和3之间,返回一个真/假标志。

  • 第 4 步。are_both_false_or_both_true 乘以 2 个布尔值,在 Python 中 True 是 1,False 是 0,所以就像 do --> 1 * 0。只有当两个值都为 True 或两者都为 True 时,变量才为 True为 False,否则始终为 False。

  • 第 5 步。get_index -> 返回 0 或 1 或 2 或 3。

  • 第 6 步。这里的 hacky 部分,使用从 get_index 接收到的索引,将 hacking_string 变量与 indexing-and-slicing 结合起来:

get_index 值始终是以下之一:“tsnr”和所采取的步骤 (4) 这些“rhtdd”中的任何一个,因此可能的组合是:

get_index = 0 = "th"  
get_index = 1 = "st"
get_index = 2 = "nd"
get_index = 3 = "rd"

终于

math.stackexchange 上询问其背后的确切数学可能会更好,或者如果有人知道添加评论或编辑我的答案会很好!

参考资料(这不是我的解决方案)

指南

【讨论】:

  • 如果这是代码高尔夫,也许吧。我不认为这很容易阅读
  • 确实是cool. 但是对于lambda 函数有别名函数名称ordinal 是有问题的(在实践中)?除了这一点,竖起大拇指!
  • 由于提问者是初学者,如果你能在代码中解释你在做什么,那就太好了。为整洁的(以某种方式)解决方案干杯!
  • the 1stnumber. :),...等输出中缺少空格。
  • @MarianD 为你添加了空间,很好! Daniel Hao 和 Waris 我现在尽我所能添加了一个解释,老实说,这是使用一些看起来很神奇但它总是有效的好数学找到的解决方案之一,同意它应该更清楚!当我添加答案时,我刚刚找到了它
【解决方案2】:

你可以这样做:

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.')

【讨论】:

    【解决方案3】:

    所以,问题是111 显示为111st 而不是111th

    你有 11ex1,我假设是“例外 1”的缩写,但你的条件:

    if number == ex1:
    

    显然不匹配111

    你可以这样做:

    if number % 100 == ex1:
    

    11111211 等将是这样。

    附注:

    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 没有任何好处。

    【讨论】:

      【解决方案4】:

      请注意,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")
      

      希望对你有所帮助。

      【讨论】:

      • 你修改了源吗?
      • 哦,你的代码没问题(+1),我必须重置我的 REPL。
      • 我认为问题在于,例如,111 获得了后缀st 而不是th,我认为这仍然是这段代码的问题。我认为您应该将第二个条件更改为 if n % 100 in [11, 12, 13]: 来解决此问题。
      • @SpoonMeiser,回答者可能不是以英语为母语的人,所以他们不知道细微差别。
      • 是的,我的母语不是英语
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-17
      • 2015-10-11
      • 1970-01-01
      相关资源
      最近更新 更多