【问题标题】:Python summing itertools.count?Python求和itertools.count?
【发布时间】:2012-11-28 10:58:24
【问题描述】:

我在使用 itertools.count 函数时遇到了一些问题,我不太明白它的作用。我希望下面的代码能够完成Project Euler problem 2

我知道我可以用一个简单的 while 循环来写这个,但是有没有办法用列表推导来做到这一点?这段代码只是冻结,因为我猜它会随着 count() 变得无穷大。我希望它会在 x > MAX 之后停止,但我知道这不会发生。有没有办法在下面的生成器表达式中停止计数?

def fib(n):
    if (n <= 1): return 1
    else: return fib(n-1) + fib(n-2)


MAX = 4000000

infiniteFib = (fib(x) for x in count())

s = (x for x in infiniteFib if x < MAX and x % 2 == 0)

print sum(s)

【问题讨论】:

  • 不管怎样,这是一个非常低效的计算斐波那契值的函数。 30 多岁之后的任何东西都需要永远返回到我的机器上,而且它非常强大。
  • 我已经记住了实际的函数,所以它不是 as 坏的。

标签: python count itertools infinite


【解决方案1】:

是的,count() 继续前进,这不是你想要的。列表推导/迭代器表达式没有灵活的退出条件(但请参阅@DSM 使用takewhile 的解决方案)。

我更喜欢只使用while

这是我对欧拉 2 的旧答案:

def SumEvenFibonacci(limit):
        x = y = 1
        sum = 0
        while (sum <= limit):
                sum += (x + y)
                x, y = x + 2 * y, 2 * x + 3 * y
        return sum

ce = SumEvenFibonacci(4000000)
print ce

【讨论】:

    【解决方案2】:

    你可以使用takewhile:

    >>> from itertools import count, takewhile, imap
    >>> sum(x for x in takewhile(lambda x: x < 4000000, imap(fib, count())) if x % 2 == 0)
    4613732
    

    【讨论】:

      【解决方案3】:

      我们只需要告诉infiniteFib 生成器何时停止生成元素。 itertools 提供了许多有用的方法来帮助解决这个问题:

      less_than_max = itertools.takewhile(lambda x: x<MAX, infiniteFib))
      even = itertools.ifilter(lambda x: x%2==0, less_than_max)
      print sum(even)
      

      我们为infiniteFib 产生的所有数字生成一个生成器,直到返回的数字大于MAX。然后我们过滤那个生成器,只选择偶数。最后我们可以总结结果。

      【讨论】:

        【解决方案4】:

        怎么样:

        def fib():
            a, b = 1, 1
            while True:
                yield b
                a, b = b, a+b
        
        sum(f for f in itertools.takewhile(functools.partial(operator.ge, 4000000), fib()) if f % 2 == 0)
        

        或者,将奇偶校验推入生成器:

        def even_fib():
            a, b = 1, 1
            while True:
                if b % 2 == 0: yield b
                a, b = b, a+b
        
        sum(itertools.takewhile(functools.partial(operator.ge, 4000000), even_fib()))
        

        【讨论】:

          【解决方案5】:

          这是另一个使用takewhile 的解决方案,但不是递归的。由于递归解决方案需要为每个 n 计算所有小于 n 的 fibs,因此速度非常慢。

          def fib_gen(only_even=False):
              one = 1
              if not only_even:
                  yield one
              two = 1
              if not only_even:
                  yield two
              while True:
                  next = one + two
                  one = two
                  two = next
                  if only_even:
                      if next % 2 == 0:
                          yield next
                  else:
                      yield next
          
          list(itertools.takewhile(lambda x: x < 4000000, fib_gen()))
          

          【讨论】:

            猜你喜欢
            • 2015-02-24
            • 2021-07-13
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-03-10
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多