Python 3:如何最好地以随机顺序遍历大文件(+100 万行)中的所有行

Python 3: How to best iterate over all lines in a big file (+1 million lines) in a random order

好的,所以我有多个文本文件,每个包含超过 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)

问题是 random.shuffle() 上的 Python Docs 明确指出(重点是我加的):

Note that even for small len(x), the total number of permutations of x can quickly grow larger than the period of most random number generators. This implies that most permutations of a long sequence can never be generated. For example, a sequence of length 2080 is the largest that can fit within the period of the Mersenne Twister random number generator.

所以问题是:

使我的设置按预期工作的最快、最有效的方法是什么?

更多信息:

我想将 line_function() 应用于随机行而不是简单地按它们所在的顺序迭代它们是有原因的。还要注意 我非常喜欢每行只处理一次.

最后,不幸的是,预先打乱文本文件或将其分成较小的文件不是一种选择。这不是我要问的。


欢迎任何见解!提前谢谢大家。

在 Python 中执行此 "quickly and efficiently" 会遇到麻烦,但如果必须的话,可以从洗牌算法开始,例如 Fisher-Yates 算法.

一旦你实现了它,加载你的文件,并记录每行开始的字节偏移量。打乱那个数组,打开你的文件,然后遍历你的数组,并从偏移量读取到下一个换行符。

对于像您提议的那样大的数据集,可以合理地预期 lines = f.readlines() 内存压力太大,需要使用偏移量的更复杂但更具可扩展性的解决方案。

为了更有效地重新运行,也许还可以考虑在生成偏移元数据后将其保存下来,这样您就不需要每次都遍历整个文件(或整个文件)。

比起大行,我更愿意对整数列表进行随机播放。
(整数是行列表中行的 index/position)
像这样:

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)

正如 Mark Dickinson 所说,您引用的文档行对 real-world 代码基本上没有实际意义。它绝对与您的代码没有任何关系。

洗牌是否对所有可能的排列产生真正均匀的随机分布并不重要。重要的是洗牌是否与这样的分布可区分,达到某种可区分性标准。 random.shuffle 在统计上无法区分完全随机洗牌,直至底层 Mersenne Twister 算法的质量,并且它的区分方式与周期无关。

您不需要做任何特别的事情来进行设置 "work as intended"。 random.shuffle 已经有效。