繁体   English   中英

Python 3:如何以随机顺序迭代大文件中的所有行(+1百万行)

[英]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文档清楚地说明了(我强调了):

注意,即使对于小len(x),x的排列总数也可以快速增长,大于大多数随机数生成器的周期。 这意味着永远不会产生长序列的大多数排列 例如,长度为2080的序列是可以在Mersenne Twister随机数生成器的周期内拟合的最大序列。

所以问题是:

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

更多信息:

我有理由将line_function()应用于随机行,而不是简单地按照它们所处的顺序迭代它们。另请注意, 我更倾向于只处理每一行一次

最后,不幸的是,将文本文件预先混洗或将其分成较小的文件是不可取的。 而不是我要问的。


任何见解都更受欢迎! Thnx提前了。

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

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

您无需执行任何特殊操作即可使设置“按预期工作”。 random.shuffle已经有效了。

我宁愿在整数列表上进行洗牌而不是大线。
(整数是行列表中行的索引/位置)
像这样的东西:

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)

在Python中“快速有效地”执行此操作会遇到麻烦,但如果必须,开始的地方将是像Fisher-Yates算法一样的混乱算法。

实现之后,加载文件,并记录每行开始的字节偏移量。 随机播放该数组,打开文件,然后遍历数组,并从偏移量读取到下一个换行符。

使用与您提议的数据集一样大的数据集,可以合理地预期lines = f.readlines()将只是过多的内存压力,需要使用偏移量来实现更复杂但更具可扩展性的解决方案。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM