【问题标题】:Refactoring ordinal number printing algorithm重构序数打印算法
【发布时间】:2021-12-30 14:18:57
【问题描述】:

我正在学习 Python 速成课程(第 5 章结束)。有一个示例问题可以打印序数 1 - 9、1"st"、2"nd" 等的正确结尾。我扩展了示例,使其适用于任何数字,如下所示。

如何才能写得更简洁?我可以查找哪些概念?我是中级 R 用户,但对 Python 很陌生。谢谢

nums = list(range(1, 50))

for i in nums:
    if i % 10 == 1 and i % 100 != 11:
        end = "st"
    elif i % 10 == 2 and i % 100 != 12:
        end = "nd"
    elif i % 10 == 3 and i % 100 != 13:
        end = "rd"
    else:
        end = "th"
    print(f"{i}{end}")

【问题讨论】:

  • 你可以使用字典,你可以在其中添加一个地方作为键和结束值作为值和例外情况
  • 不确定这里的简洁是什么意思,但 DRY 说 i % 10i % 100 应该是可变的。如果您所做的只是迭代它,range 也不需要 list(。除了这些 认为 if-elif-else 是要走的路,字典会因为 != 条件的存在而混淆。

标签: python dictionary lookup


【解决方案1】:

如 cmets 中所述,dict 可用于这样的查找逻辑。复杂性是当数字的最后两位数字在“十几岁”时。在您的情况下有用的示例dict 是:

endings = {1: 'st', 2: 'nd', 3: 'rd'}

你可以在你的for循环体中使用它:

if 10 < i % 100 < 20:
    end = 'th'
else:
    end = endings.get(i % 10, 'th')  # The second arg to the `get` method returns a default value

更进一步,您可以通过结合查找逻辑并利用逻辑短路来使其更加简洁:

end = endings.get(not 10 < i % 100 < 20 and i % 10, 'th')

但我真的不建议这样做!这对读者来说非常恶心和困惑。

说实话,您的原始示例是这些选项中最易读的。在选择做什么之前,您必须权衡简洁性和可读性的价值。

【讨论】:

    【解决方案2】:

    没有那么多 if/else 条件的替代方案

    values_10 = [1, 2, 3]                                          # Numbers to equal mod 10
    exceptions_100 = [11, 12, 13]                                  # Numbers not to equal mod 100
    endings = ['st', 'nd', 'rd', 'th']                             # Set of endings
    for i in range(1, 50):
        i_mod_10, i_mod_100 = i % 10, i % 100                      # Compute i mod 10 and i mod 100
        try:
            idx = values_10.index(i_mod_10)                        # Get index of match for 1, 2, or 3 (if exists)
            # Since no exception ending was 1, 2, or 3
            # end is based on whether i_mod_100 matches it's corresponding value
            end = endings[-1] if i_mod_100 == exceptions_100[idx] else endings[idx]  
        except ValueError:
            end = endings[-1]                                       # i_mod_10 was not 1, 2, or 3
        print(f"{i}{end}")
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-07-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多