Итак, у меня есть несколько текстовых файлов, каждый из которых содержит более 500 000 или даже 1 000 000 строк.

В настоящее время я делаю что-то вроде этого:

import random

def line_function(line):
    # Do something with given line

def random_itteration(filepath):
    with open(filepath) as f:
        lines = f.readlines()
        random.shuffle(lines)
        for line in lines:
            result = line_function(line)

Дело в том, что Документы Python в random.shuffle() четко заявляют ( Акцент добавлен мной):

Обратите внимание, что даже для маленьких len (x) общее количество перестановок x может быстро расти больше, чем период самого случайного числа генераторы. Это означает, что большинство перестановок длинной последовательности могут никогда не быть сгенерированным . Например, последовательность длиной 2080 является Наибольший, который может вписаться в период случайного Mersenne Twister генератор чисел.

Итак, вопрос в том,

Какой самый быстрый и эффективный способ заставить мою установку работать так, как задумано?

Дополнительная информация:

Есть причина, по которой я хочу применить line_function () к произвольной строке, а не просто перебирать их в той последовательности, в которой они находятся. Также обратите внимание, что я предпочитаю обрабатывать каждую строку только один раз .

Наконец, перетасовывание текстового файла или разделение его на более мелкие файлы, к сожалению, не вариант. И это не то, что я спрашиваю.


Любые идеи более чем приветствуются! Заранее спасибо, ребята.

4
Montmons 27 Фев 2018 в 20:28

3 ответа

Лучший ответ

Как говорит Марк Дикинсон, строка документа, которую вы цитируете, практически не имеет практического значения для реального кода. Это определенно не имеет никакого отношения к вашему коду.

Не имеет значения, производит ли случайное распределение действительно равномерное случайное распределение по всем возможным перестановкам. Важно то, является ли shuffle различимым от такого распределения, вплоть до некоторого стандарта различимости. random.shuffle статистически неотличим от абсолютно случайного перемешивания до качества лежащего в основе алгоритма Мерсенна-Твистера, а способы его различения не имеют никакого отношения к периоду.

Вам не нужно делать ничего особенного, чтобы ваши настройки работали как задумано. random.shuffle уже работает.

5
user2357112 supports Monica 27 Фев 2018 в 18:38

У вас будут проблемы с выполнением этого «быстро и эффективно» в Python, но если вам необходимо, то для начала будет использоваться алгоритм тасования, такой как алгоритм Фишера-Йейтса.

Как только вы это реализуете, загрузите ваши файлы и запишите, с какого байта смещается каждая строка. Перемешайте этот массив, откройте ваши файлы, затем выполните итерацию по вашему массиву и прочитайте смещение до следующей новой строки.

С такими большими наборами данных, как вы предлагаете, разумно ожидать, что lines = f.readlines() будет просто слишком сильно загружать память, требуя более сложного, но более масштабируемого решения с использованием смещений.

Для более эффективного повторного запуска, возможно, также стоит сохранить метаданные смещения после их создания, чтобы вам не приходилось каждый раз просматривать весь файл (или все файлы).

-1
Adam Barnes 27 Фев 2018 в 17:38

Я предпочел бы сделать случайный случай в списке целых чисел, а не в огромных строках.
(Целые числа - индекс / позиция строки в списке строк)
Примерно так:

import random
from random import randint

def line_function(line):
    # Do something with given line

def random_itteration(filepath):
    with open(filepath) as f:
        lines = f.readlines()
        count = len(lines)
        #random_index_list = random.shuffle(list(xrange(count)))
        random_index_list = random.sample(range(count+1),count)
        for index in random_index_list:
            result = line_function(lines[index])

        #shuffled_lines = random.shuffle(lines)
        #for line in shuffled_lines:
        #    result = line_function(line)
0
murphy1310 27 Фев 2018 в 21:14