如何在 Python 中对存储在文件中的非常大的列表进行打乱?

2023-12-14

我需要确定性地生成一个包含 0 到 2^32-1 数字的随机列表。

这将是一种天真的(并且完全不起作用)的做法,只是为了清楚我想要什么。

import random
numbers = range(2**32)
random.seed(0)
random.shuffle(numbers)

我尝试过列出清单numpy.arange()并使用 pycrypto 的random.shuffle()对其进行洗牌。制作列表占用了大约 8GB 的​​内存,然后进行洗牌则将其提高到 25GB 左右。我只有 32GB 可以给。但这并不重要,因为...

我尝试将列表切成 1024 个切片并尝试上述操作,但即使其中一个切片也花费了太长的时间。我将其中一片切成 128 个更小的片,然后that每个大约花费 620 毫秒。如果是线性增长的话,那就意味着整个事情需要大约22个半小时才能完成。听起来不错,但它并不是线性增长的。

我尝试过的另一件事是为每个条目生成随机数并将其用作新位置的索引。然后,我沿着列表向下查找并尝试将数字放置在新索引处。如果该索引已被使用,则该索引会递增,直到找到空闲索引。这在理论上是有效的,并且它可以完成大约一半的工作,但接近尾声时,它必须不断搜索新的位置,多次绕行列表。

有什么办法可以解决这个问题吗?这是一个可行的目标吗?


计算所有值似乎是不可能的,因为Crypto计算一个随机整数大约需要一毫秒,所以整个工作需要几天的时间。

这是作为生成器的 Knuth 算法实现:

from Crypto.Random.random import randint  
import numpy as np

def onthefly(n):
    numbers=np.arange(n,dtype=np.uint32)
    for i in range(n):
        j=randint(i,n-1)
        numbers[i],numbers[j]=numbers[j],numbers[i]
        yield numbers[i]

For n=10:

gen=onthefly(10)
print([next(gen) for i in range(9)])
print(next(gen))
#[9, 0, 2, 6, 4, 8, 7, 3, 1]
#5

For n=2**32,生成器需要一分钟来初始化,但调用的时间复杂度为 O(1)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 Python 中对存储在文件中的非常大的列表进行打乱? 的相关文章

随机推荐