好的,所以我有多个文本文件,每个文件包含超过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()
{{1}}清楚地表明了(我强调的是):
请注意,即使是小len(x),x的排列总数也是如此 可以快速增长大于大多数随机数的时期 发电机。 这意味着长序列的大多数排列都可以 永远不会被生成。例如,长度为2080的序列是 最大的,可以适应梅森Twister期间随机 数字生成器。
所以问题是:
使我的设置按预期工作的最快和最有效的方法是什么?
更多信息:
有一个原因我想将line_function()应用于随机行,而不是简单地按照它们所处的顺序迭代它们。还要注意我非常喜欢只处理每一行
最后,不幸的是,将文本文件预先混洗或将其分成较小的文件是不可取的。并不是我要问的。
欢迎任何见解! Thnx提前了。
答案 0 :(得分:5)
正如Mark Dickinson所说,你引用的文档行对现实世界的代码基本没有实际意义。它绝对与您的代码没有任何关联。
shuffle是否在所有可能的排列上产生真正均匀的随机分布并不重要。重要的是洗牌是否可以与这种分布区分开来,直到某种可区分标准。 percona_1 | Initializing database
percona_1 | 2018-02-27T18:21:40.471171Z 0 [Warning] 'NO_ZERO_DATE', 'NO_ZERO_IN_DATE' and 'ERROR_FOR_DIVISION_BY_ZERO' sql modes should be used with strict mode. They will be merged with strict mode in a future release.
percona_1 | 2018-02-27T18:21:40.471336Z 0 [Warning] 'NO_AUTO_CREATE_USER' sql mode was not set.
percona_1 | 2018-02-27T18:21:40.509126Z 0 [Warning] Setting lower_case_table_names=2 because file system for /var/lib/mysql/ is case insensitive
percona_1 | 2018-02-27T18:21:40.511757Z 0 [Warning] One can only use the --user switch if running as root
percona_1 |
percona_1 | 2018-02-27T18:21:42.900823Z 0 [ERROR] InnoDB: Operating system error number 22 in a file operation.
percona_1 | 2018-02-27T18:21:42.901071Z 0 [ERROR] InnoDB: Error number 22 means 'Invalid argument'
percona_1 | 2018-02-27T18:21:42.901164Z 0 [ERROR] InnoDB: File ./ib_logfile101: 'aio write' returned OS error 122. Cannot continue operation
percona_1 | 2018-02-27T18:21:42.901187Z 0 [ERROR] InnoDB: Cannot continue operation.
docker_percona_1 exited with code 3
在统计上与完全随机的混乱无法区分,直到Mersenne Twister算法的质量,并且它的可区分方式与周期无关。
您无需执行任何特殊操作即可使设置“按预期工作”。 random.shuffle
已经有效。
答案 1 :(得分:0)
我宁愿在整数列表上进行洗牌而不是大线
(整数是行列表中行的索引/位置)
这样的事情:
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)
答案 2 :(得分:-1)
你很难做到这一点"快速有效地"在Python中,但如果必须,开始的地方将是一个像Fisher-Yates算法那样的混乱算法。
实现后,加载文件,并记录每行开始的字节偏移量。随机播放该数组,打开文件,然后遍历数组,并从偏移量读取到下一个换行符。
使用与您一样大的数据集,可以合理地预期lines = f.readlines()
将只是过多的内存压力,需要使用偏移来实现更复杂但更具可扩展性的解决方案。
为了更有效地重新运行,也可以考虑在生成后保存偏移元数据,这样您就不必每次都遍历整个文件(或整个文件)。