我基本上是在寻找可能对此有意见的其他人的反馈。以下不是我正在研究的内容,但示例代码确实重现了这个问题。
我有一个电源设置生成器,如果我正在发送的基本列表,则返回所有排列。我需要对生成的集进行排序(在我的实际情况中,返回的集是具有我想要排序的值的元组通过,下面的例子演示了没有它的问题。
问题是当我在电源设置发生器上使用sorted()时,它会耗尽内存使用量。我意识到2 ^ 50是一个非常大的数字,但没有排序的内存使用是非常平坦的,所以我想知道是否有更好的方法来排序超大量的集合,而不会在一两分钟内耗尽内存。这是在使用Python 2.6.5的Ubuntu上运行的。 (在这种情况下也需要)
def gen_powerset(seq):
if len(seq) <= 1:
yield seq
yield []
else:
for i in gen_powerset(seq[1:]):
yield [seq[0]]+i
yield i
def main():
initialSet = range(50)
powerset = sorted(gen_powerset(initialSet))
for i in powerset:
print i
if __name__ == "__main__":
main()
免责声明:如果您尝试运行此示例,请注意您的内存利用率。 Ctrl-C示例如果它接近90%,因为您的操作系统将开始将内存交换到磁盘。如果样品仍然在运行,那么您的磁盘负载将会出现峰值,并且确实会使速度变慢,从而导致首先难以杀死样品。
答案 0 :(得分:4)
没有sorted
,您永远不需要一次存储超过1或2个值 - 它们是在需要时计算的,因为您使用的是生成器(yield
)。不幸的是,没有好的方法可以在不知道整个事情的情况下对列表进行排序(在您查看所有项目之前,您无法从排序中获得值,以确保您拥有该项目有最小的)。
当然,如果你有2个已排序的子列表,你可以懒惰地合并它们,这样你可以构建一个排序,它不会根据合并排序一次性将所有内容存储在内存中,但它在一般情况下会非常低效。
答案 1 :(得分:2)
sorted
内存使用率较高的原因是它必须立即将所有项目加载到内存中。由于您编写了一个生成器,它一次只生成一个元素,而您使用它的方式一次只使用一个值,因此Python不需要同时保留所有项目。但是如果没有全部可用的话,你就无法对它们进行排序。
只要您进行排序,就无法解决这个问题,因为排序必须包含所有元素。
解决问题的唯一方法是重写您的powerset生成器,以按您想要的顺序生成项目。根据您想要的顺序,这可能是也可能不可能。
答案 2 :(得分:2)
你正在使用一个只在消耗之前一次创建一个值的生成器,这非常有效。 sorted
函数需要将其转换为列表,以便它们一次驻留在内存中。没有办法解决它。