生成巨大列表的随机排列(Python)
Generate random permutation of huge list (in Python)
我想创建数字 [1,2,...,N]
的随机排列,其中 N
是一个大数字。所以我不想将排列的所有元素存储在内存中,而是迭代我的特定排列的元素而不将以前的值保存在内存中。
知道如何在 Python 中做到这一点吗?
这是一个普遍问题,而不是 Python 特有的问题。在大多数语言中,即使使用迭代器来使用结构,整个结构也会保存在内存中。因此,迭代器主要用作 "functional" 工具而不是 "memory-optimization" 工具。
在 python 中,很多人最终会因为拥有非常大的结构(字典等)而使用大量内存。但是,程序的所有变量-对象都会以任何方式存储在内存中。唯一的解决方案是数据的序列化(保存在文件系统、数据库等中)。
因此,对于您的情况,您可以创建一个自定义函数来创建排列列表。但是,不是将排列的每个元素添加到列表中,而是将元素保存在文件中(或具有相应结构的数据库中)。然后,您将能够从文件(或数据库)中逐一检索每个排列,而无需将整个列表放入内存中。
但是,如前所述,您必须始终知道您当前处于哪种排列。为了避免从数据库中检索所有已创建的排列(这会造成相同的瓶颈),您可以为每个包含先前生成的排列中使用的符号的位置创建一个索引(并创建添加符号和预定义序列的排列) .
一种可能是使用加密。由于加密是可逆的,即一对一,对于给定的密钥,您将得到与加密相同但顺序不同的数字。
您需要一个块大小足以包含最大 N 的块密码。在 ECB 模式下使用 DES 以获取 N = 2^64 - 1。在 ECB 模式下使用 AES 以获取 N = 2^128 - 1。对于其他尺寸,请使用 Hasty Pudding cipher, which has variable block size, or write your own simple Feistel cipher。我假设您只需要随机播放,而不是加密安全的随机播放。
如果输出大于N,则重新加密直到小于N,1对1属性确保大数链也是唯一的。
无需将整个数组存储在内存中,可以根据需要对每个数字进行加密。只需要密钥和密码算法。一个轻微的并发症是分组密码在 [0 ... N-1] 上工作;您可能需要一些额外的代码来处理极端情况。
我想创建数字 [1,2,...,N]
的随机排列,其中 N
是一个大数字。所以我不想将排列的所有元素存储在内存中,而是迭代我的特定排列的元素而不将以前的值保存在内存中。
知道如何在 Python 中做到这一点吗?
这是一个普遍问题,而不是 Python 特有的问题。在大多数语言中,即使使用迭代器来使用结构,整个结构也会保存在内存中。因此,迭代器主要用作 "functional" 工具而不是 "memory-optimization" 工具。
在 python 中,很多人最终会因为拥有非常大的结构(字典等)而使用大量内存。但是,程序的所有变量-对象都会以任何方式存储在内存中。唯一的解决方案是数据的序列化(保存在文件系统、数据库等中)。
因此,对于您的情况,您可以创建一个自定义函数来创建排列列表。但是,不是将排列的每个元素添加到列表中,而是将元素保存在文件中(或具有相应结构的数据库中)。然后,您将能够从文件(或数据库)中逐一检索每个排列,而无需将整个列表放入内存中。
但是,如前所述,您必须始终知道您当前处于哪种排列。为了避免从数据库中检索所有已创建的排列(这会造成相同的瓶颈),您可以为每个包含先前生成的排列中使用的符号的位置创建一个索引(并创建添加符号和预定义序列的排列) .
一种可能是使用加密。由于加密是可逆的,即一对一,对于给定的密钥,您将得到与加密相同但顺序不同的数字。
您需要一个块大小足以包含最大 N 的块密码。在 ECB 模式下使用 DES 以获取 N = 2^64 - 1。在 ECB 模式下使用 AES 以获取 N = 2^128 - 1。对于其他尺寸,请使用 Hasty Pudding cipher, which has variable block size, or write your own simple Feistel cipher。我假设您只需要随机播放,而不是加密安全的随机播放。
如果输出大于N,则重新加密直到小于N,1对1属性确保大数链也是唯一的。
无需将整个数组存储在内存中,可以根据需要对每个数字进行加密。只需要密钥和密码算法。一个轻微的并发症是分组密码在 [0 ... N-1] 上工作;您可能需要一些额外的代码来处理极端情况。