我正在使用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
你读入的行数在哪里。 这里有一个更详细的算法(不要试图仅仅根据我在这篇文章中告诉你的内容来实现它单独段落)。
收到一只叮咚
TA贡献1821条经验 获得超4个赞
最简单的解决方案是在阅读每一行时做出决定,是测试它还是丢弃它......让你的决定随机化,这样你就不需要将整个东西保存在 RAM 中......然后通过运行测试后通过文件...您也可以使用非随机分布测试(例如在 X 字节或 X 行等之后)执行相同的样式
- 3 回答
- 0 关注
- 399 浏览
添加回答
举报
0/150
提交
取消