从文件中提取与另一个文件中的条件匹配的某些行
Extracting certain rows from a file that match a condition from another file
所以首先,我知道类似的问题有一些答案,但是。。。我的问题与速度和内存效率有关。
我有一个60 GB的文本文件,其中有17个字段和460368082条记录。第3列有个人的ID,同一个人在该文件中可以有多条记录。让我们调用这个文件File A
。
我有第二个文件File B
,它的ID为1000000个人,我想提取File A
中ID为File B
的行。
我有一台windows PC,我对用C或Python或其他更快的语言来做这件事持开放态度。。。但不确定如何快速有效地完成。
根据我的计算,到目前为止,我提出的每一个解决方案都需要1.5年以上的时间。
您想要的是一个排序合并联接。其想法是对要加入的列(ID)上的文件A进行排序。对要加入的列(ID)上的文件B进行排序。然后使用合并算法读取这两个文件,忽略两者不匹配的文件。
对文件进行排序可能需要创建中间文件。
如果数据在带有分隔符的文本文件中,您也可以使用linux排序命令行实用程序来执行排序。
sort -k3,3 -t'|' fileA > fileA.sorted
sort fileB > fileB.sorted
dos2unix fileB.sorted #make sure the line endings are same style
dos2unix fileA.sorted #make sure the line endings are same style
如果dos2unix不可用,这可能被用作替代
sort -k3,3 -t'|' fileA | tr -d 'r' > fileA.sorted
sort fileB | tr -d 'r' > fileB.sorted
加入文件
join -1 3 -2 1 -t'|' fileA.sorted fileB.sorted
另一种选择是,如果您有足够的RAM,则可以在内存中以HashMap类型的结构加载文件B。然后读取文件A,并在HashMap中查找匹配项。我认为任何一种语言都可以,只是取决于你对哪种语言更熟悉。
这取决于,如果它没有排序,你将不得不搜索整个东西,我会使用多个线程。如果你要多次搜索,我也会创建一个索引。
如果你有大量的内存,你可以创建一个哈希表来保存字符串。然后,您可以将第一个文件中的所有字符串加载到哈希表中。然后,从第二个文件中一次加载一个字符串。对于每个字符串,请检查它是否在哈希表中。如果是,请报告匹配。这种方法使用O(m)内存(其中m是第一个文件中的字符串数),并且至少需要Ω(m+n)时间,甚至可能更多,这取决于哈希函数的工作方式。这也是(几乎可以肯定的)解决问题最简单、最直接的方法。
如果您的ram很少,但有大量的磁盘空间:https://en.wikipedia.org/wiki/External_sorting,您可以获得O(n log n)时间。
听起来您想要做的是首先读取File B
,收集ID。您可以将ID存储在set
或dict
中。
然后读取File A
。对于File A
中的每一行,提取ID,然后通过检查set
或dict
中的成员身份来查看它是否在File B
中。如果没有,则跳过该行,继续下一行。如果是,则根据需要处理该行。
- 根据特定条件从文件中检索每个令牌
- 为什么我可以将 ifstream 文件置于 if 条件?
- GDB / C++ - 根据循环条件将多个变量记录到输出文件中
- 使用文件锁定的进程之间的条件变量
- C++,使用自己的条件搜索文件中的字符串
- 计算文本文件中行数的最佳条件是什么
- 使用多个.cpp文件,可以替代C 中的条件汇编
- 有条件地将文件包含在C++标头中
- 如何使预处理器 #if 以另一个不同文件中的值为条件
- 从文件中逐行读取条件
- QT Pro文件条件液体
- 即使不满足条件,也会重置文本文件.(C++)
- 有条件地将文件添加到项目中C++库中
- 生成文件中的条件变量
- 如何在Visual C++中有条件地包含一个不存在的文件
- 有条件地提示安装文件夹对话框
- 我应该使用什么条件来停止文件读取循环
- #if 条件区域是否可以跨越包含文件边界
- 系统头文件中的条件编译
- 希望使用 C++ 有条件地连接文本文件中的字符串