Python: Альтернатива для генератора огромного списка - PullRequest
0 голосов
/ 02 мая 2020

Для пакета, который я пишу, мне нужны уникальные числа от 0 до 2 ** 33 в случайном порядке. Первоначально я пытался использовать генератор следующим образом:

def randomnumber(NUM):
    List = [i for i in range(NUM)]
    List.shuffle()
    index = 0
    while index < NUM:
          index += 1
          yield List[index-1]

Но поскольку в моем случае NUM равен 2 ** 33, этот код просто невозможен. Я попытался записать все цифры в текстовый файл из bash и обнаружил, что размер файла составляет 93,6 ГБ (что действительно огромно и намного больше, чем моя оперативная память). Затем я перетасовываю содержимое файла с помощью terashuf и читаю каждую строку через него с помощью linecache.

Также я использую модуль многопроцессорной обработки (в частности, apply_asyn c) и действительно нужно передать этот объект генератора в качестве аргумента. Но python выдал ошибку, заявив, что он не может использовать объект генератора в процессах пула. Я прошел несколько вопросов по SO, и один из ответов - создать список этих чисел из генератора для нескольких чисел и передать их в качестве аргументов функции, работающей параллельно, но это тоже не сработало.

Поэтому у меня есть вопрос, каким образом мы можем создать генератор, который выполняет запланированную работу (давать случайное уникальное число в диапазоне от 0 до 2 ** 33) или каким-либо другим способом сделать это, поскольку я не хочу тасовать содержимое файла снова и снова (занимает много времени)

1 Ответ

0 голосов
/ 02 мая 2020

Как я понимаю, суть вашего кода заключается в генерации случайного целого числа от 0 до NUM. И в вашем случае, NUM будет 2**33.

Следующий код сделает это, и вы можете изменить NUM без проблем:

import math
import random


def generate_random(num):
    yield random.randint(0, num) 

#setting seed to get consistent results
random.seed(0)

# Now, let's use this simple function to generate
# 5 different random number between `0` and `2**33`:
NUM = math.pow(2, 33)
for i in range(10):
    print(next(generate_random(NUM)))

# This would print these five numbers
# 7921731533
# 1806341205
# 6490875490
# 6341935620
# 3900315155
...