【问题标题】:Returning even and odd numbers in Python在 Python 中返回偶数和奇数
【发布时间】:2020-04-23 19:52:26
【问题描述】:

我在回答以下问题的 Python 测验时遇到了一些问题:

给定两个数字 X 和 Y,编写一个函数: 返回 X 和 Y 之间的偶数,如果 X 大于 Y,则返回 x 和 y 之间的奇数

例如,取整数 10 和 2 。该函数将返回 2 到 10 之间的所有偶数。

我真的很感激一些帮助,因为我还是个新手

这是我的代码:

def number_game(x,y):
  num = range(x,y)
  for e in num:
    if x > y:
      return e%2 == 0
    else:
      return e%3 == 0

这里是测试用例:

test.assert_equals(number_game(2,12), [3, 5, 7, 9, 11])
test.assert_equals(number_game(0,0), [])
test.assert_equals(number_game(2,12), [3, 5, 7, 9, 11])
test.assert_equals(number_game(200,180), [180, 182, 184, 186, 188, 190, 192, 194, 196, 198])
test.assert_equals(number_game(180,200), [181, 183, 185, 187, 189, 191, 193, 195, 197, 199])

【问题讨论】:

  • return e%2 == 0 是布尔值,而不是数值
  • num = range(x,y) 这应该是非包容性的吗?
  • 您的 e%3 比较不太正确 - 您应该在两种情况下比较 a%2,但要比较不同的数字。试着弄清楚自己是哪一个!
  • @vash_the_stampede:基于测试用例,上界独占。因为否则200 应该在最后一个测试用例中。
  • 只要使用number_game = lambda x, y: [i for i in filter(lambda i: i%2 == (x > y), range(*(x, y+1) if y > x else (y, x+1)))]

标签: python python-3.x


【解决方案1】:

这里有一些问题:

  1. 如果x >= y,则range(x, y)为空,因此for循环不会枚举任何值;
  2. e % 2 == 0e % 3 == 0 是相等检查,因此将返回一个布尔值;
  3. e % 3 == 0 检查数字是否可以被3 整除,而不是奇数;和
  4. 一旦你返回一些东西,你就会逃出函数。

我们可以编写一个避免循环的函数,首先检查数字,然后构造正确的range(..)对象,例如:

def number_game(x,y):
    if x > y:
        if y % 2 == 1:
          y += 1
        return list(range(y, x, 2))
    else:
        if x % 2 == 0:
            x += 1
        return list(range(x, y, 2))

例如:

>>> number_game(14, 25)
[15, 17, 19, 21, 23]
>>> number_game(15, 25)
[15, 17, 19, 21, 23]
>>> number_game(25, 14)
[14, 16, 18, 20, 22, 24]
>>> number_game(25, 13)
[14, 16, 18, 20, 22, 24]
>>> number_game(2,12)
[3, 5, 7, 9, 11]
>>> number_game(0,0)
[]
>>> number_game(2,12)
[3, 5, 7, 9, 11]
>>> number_game(200,180)
[180, 182, 184, 186, 188, 190, 192, 194, 196, 198]
>>> number_game(180,200)
[181, 183, 185, 187, 189, 191, 193, 195, 197, 199]

代码可以更紧凑:

def number_game(x,y):
    if x > y:
        return list(range(y + (y%2), x, 2))
    else:
        return list(range(x+1-(x%2), y, 2))

因此,我们首先检查是否x > y,(或不)。因为如果x > y我们应该构造一个range(y, x, 2),但是问题可能是y是奇数,所以我们先检查它是否是奇数,如果是,我们增加值。

如果x <= y 也会发生类似的情况:我们构造了一个range(x, y, 2),但如果x 是偶数,我们也将其递增。

因为我们采用了两个步骤(range(..) 中的最后一个参数),这也将更有效地构造列表,因为range(..) 函数不会测试一个数字是否为偶数/odd,但只需使用 2 递增变量。

如果您希望“实现”可迭代对象(将元素放在列表中),而只是返回相关的range(..) 可迭代对象,我们可以这样做:

def number_game(x,y):
    if x > y:
        return range(y + (y&1), x, 2)
    else:
        return range(x+1-(x&1), y, 2)

这样做的好处是range(..) 允许快速的成员检查,范围也可以非常有效地分割等等。所以你保留range(..) 对象,你可以后处理它.

【讨论】:

    【解决方案2】:

    使用列表推导的更 Pythonic 方式

    def number_game(x,y):
        if x > y:
            return [n for n in range(y,x) if n%2==0]
        elif y==x:
            return []
        else:
            return [n for n in range(x,y) if n%2!=0]
    

    【讨论】:

    • 为什么要在你的列表组合中打扰那些if 子句?您应该使用 rangestep 参数。
    • 好点,但由于 OP 使用了 mod 运算符,但并不完全正确,我认为在实际中展示它是有帮助的。另外,我认为这是更好的自记录代码,但这只是我的偏好
    • 公平点。它所做的工作是它需要做的两倍以上的事实在这里并不重要。除非 x 和 y 之间存在巨大差异。 ;)
    • test.assert_equals(number_game(1000000000000000,-100000000000000), [-100000000000000, -99999999999998,... 让我咯咯笑!
    【解决方案3】:

    看看使用Generatorsyield关键字)的解决方案

    def number_game(x,y):
      num = range(min(x,y),max(x,y))
      for e in num:
        if x > y and e%2 == 0:
          yield e
        elif x < y and e%2 != 0:
          yield e
    
    # you have to materialize generators to lists before comparing them with lists
    print(list(number_game(2,12)) == [3, 5, 7, 9, 11])
    print(list(number_game(0,0)) == [])
    print(list(number_game(2,12)) == [3, 5, 7, 9, 11])
    print(list(number_game(200,180)) == [180, 182, 184, 186, 188, 190, 192, 194, 196, 198])
    print(list(number_game(180,200)) == [181, 183, 185, 187, 189, 191, 193, 195, 197, 199])
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-07-07
      • 2013-04-13
      • 2017-02-06
      • 2019-03-19
      • 2013-12-11
      • 2011-12-31
      • 1970-01-01
      相关资源
      最近更新 更多