遍历一个大列表

Iterating over a large list

我有一个 [465868129, 988379794] 范围内的列表,包括这两个值。当我使用以下代码时,出现内存错误。我能做什么?

r = [465868129, 988379794]
list = [x for x in xrange(r[0], r[1]+1)]

除非你有很好的理由将列表项存储在列表中,否则迭代生成器,这样 Python 不需要分配大量内存(导致你的内存错误)创建该列表:

init, end = (465868129, 988379794)
items = xrange(init, end + 1)

for item in items:
    #Do something with item

要计算任意范围内的正方形,请考虑以下公式:

import math

number_of_squares = int(math.sqrt(end) - math.sqrt(init)) + 
                    op(is_perfect_square(init), is_perfect_square(end))

is_perfect_square(n) 本身就是另一个问题,如果有兴趣,请查看 this post

当区间init (or/and/neither) end的始末为完全正方形时,op用于调整正方形的个数。所以我们需要一个具有以下特点的函数:

  • 两个数字都是完全正方形:例如:25,64 => 8 - 5 = 3(并且在该范围内有 4 个正方形)。 (它应该再加 1)
  • 结束是一个完美的正方形:例如:26,64 => 8 - 5 = 3(该范围内有 3 个正方形)。 (正确 => 总和应为 0)
  • Init 是一个完美的正方形:例如:25,65 => 8 - 5 = 3(该范围内有 4 个正方形)。 (它应该再加 1)
  • None 的数字是质数:例如:26、65 => 8 - 5 = 3(该范围内有 3 个正方形)(正确 => 总和应为 0)

所以我们需要一个具有以下特点的运算符,根据以往的例子:

  • 1 op 1 = 1(两个数都是完全平方数)
  • 0 op 1 = 0(结尾是正方形)
  • 1 op 0 = 1(初始化为正方形)
  • 0 op 0 = 0(None 个数是完全平方数)

请注意,max 函数几乎可以满足我们的需求,但它在第二种情况下失败了 max(0,1) = 1,它应该是 0。

因此,看起来结果只取决于第一个运算符:如果是 1,则结果为 1,另一方面,如果为 0,则 returns0。

因此,考虑到这一点很容易编写函数:

import math

number_of_squares = int(math.sqrt(end) - math.sqrt(init)) + 
                    int(is_perfect_square(init))

感谢@kojiro,我们有了这种方法(有类似的想法),更容易阅读:

from math import sqrt, floor, ceil

number_of_squares = 1 + floor(sqrt(end)) - ceil(sqrt(init))

您可以直接遍历 xrange 而不是创建列表。

for x in xrange(r[0], r[1] + 1):
    ...

但是在如此大的范围内迭代是一种非常非常慢的查找正方形的方法。您 运行 内存不足这一事实应该提醒您需要采用不同的方法。

更好的方法是取每个端点的平方根,然后在平方根之间迭代。平方根之间的每个整数,当平方时,会给你一个你正在搜索的数字。

事实上,如果您足够聪明,您可以通过一个列表理解生成所有方块,并完全避免显式 for 循环。