为了账号安全,请及时绑定邮箱和手机立即绑定

在 go 中从文本文件中读取随机行

在 go 中从文本文件中读取随机行

Go
森栏 2021-07-28 17:03:17
我正在使用encoding/csv读取和解析一个非常大的 .csv 文件。我需要随机选择行并通过一些测试。我目前的解决方案是读取整个文件,如reader := csv.NewReader(file)lines, err := reader.ReadAll()然后从lines其中随机选择行明显的问题是阅读整个内容需要很长时间,而且我需要大量内存。提问:我的问题是,encoding/csv给我的io/reader是有没有用它来阅读,而不是一次加载整个事情乱行的方法吗?这io/reader与其说是一个实际问题,不如说是一个需要了解更多的好奇心,因为很可能最终读取一次并在内存中访问它更有效,而不是继续在磁盘上寻找随机行。
查看完整描述

3 回答

?
慕尼黑5688855

TA贡献1848条经验 获得超2个赞

Apokalyptik 的答案最接近你想要的。读者是流媒体,所以你不能只是跳到一个随机的地方(本身)。

天真地选择在读入时保留任何给定行的概率可能会导致问题:您可能在没有保留足够输入行的情况下到达文件末尾,或者您可能太快地保留行而没有得到很好的样本。两者都比正确猜测更有可能,因为您事先不知道文件中有多少行(除非您先迭代一次以计算它们)。

您真正需要的是水库取样

基本上,逐行读取文件。每一行,你都可以这样选择是否持有:你阅读的第一行,你就有1/1机会持有。阅读第二行后,您有1/2机会用这一行替换您持有的内容。在第三行之后,您有1/2 * 2/3 = 1/3机会抓住那一行。因此,你有1/N机会抓住任何给定的行,N你读入的行数在哪里。 这里有一个更详细的算法(不要试图仅仅根据我在这篇文章中告诉你的内容来实现它单独段落)。


查看完整回答
反对 回复 2021-08-02
?
收到一只叮咚

TA贡献1821条经验 获得超4个赞

最简单的解决方案是在阅读每一行时做出决定,是测试它还是丢弃它......让你的决定随机化,这样你就不需要将整个东西保存在 RAM 中......然后通过运行测试后通过文件...您也可以使用非随机分布测试(例如在 X 字节或 X 行等之后)执行相同的样式


查看完整回答
反对 回复 2021-08-02
  • 3 回答
  • 0 关注
  • 399 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信