我需要2个utf-8文本文件。在文件的每一行中都有字符串,可以包含特定于语言的字符,如Ü,Ö,±,ę。字符串是随机顺序和长度,可以重复。在第一个文件中至少有3百万行(它可以轻松超过1 mld行)。第二个文件较小,通常可以获得大约40,000行(但可以更大)。
我需要创建一个新文件,其中包含文件1中的条目,其中删除的条目出现在文件二和所有重复条目中。
目前我正在对这两个文件进行排序并删除重复的条目。接下来我将它们写入新文件,同时检查它们是否出现在第二个文件中。
有没有更快的方法呢?
修改
内存是个问题。我不将这个字符串复制到内存中,对文件进行操作。我的朋友建议不要复制到内存,而是处理文件流。此执行时间显着下降。
计算机管理员不想在其上安装数据库。
在循环中对我的代码符号进行排序之后:
if stringFromFile1 < stringFromFile2 then writeToFile3 and get next stringFromFile1
else if stringFromFile1 == stringFromFile2 then dropStringFromFile1 and get next stringFromFile1
else if stringFromFile1 > stringFromFile2 then get next stringFromFile2 and go to line 1
答案 0 :(得分:0)
如果您有可用的数据结构,例如哈希集,则只需迭代文件并添加每一行。集合不允许重复,并且散列集应为您提供检查元素是否已存在的常量方法(至少在Java中,add
方法检查元素是否存在,如果它没有,它会在恒定时间内将项目添加到集合中。
一旦浏览了两个文件,就可以迭代哈希集并将其内容存储到文件中。这应该为您提供一个可以线性时间的算法。
忘记提及:我假设您没有内存消耗限制。如果这样做,您可能希望尝试将每一行保存到数据库,并使用每行的哈希作为主键。插入带有两个主键的元素应该会失败,从而确保数据库中有唯一的字符串。完成插入后,您可以检索数据库中的值并将其存储到文件中。
答案 1 :(得分:0)
我的建议是预处理文件二并从中形成树结构。例如,假设你有这种文件二:
bad
bass
absent
然后您的树结构将是这样的:
BEGIN -> b -> a -> d -> END
| |
| + -> s -> s -> END
|
+-> a -> b -> s -> e -> n -> t -> END
END
指定单词分隔符(无论是空格还是新行或其他内容)
然后将文件1打开到文件流中并逐字节地读出。一旦遇到文件的开头或在分隔符后选择下一个字符,就开始走树了。如果使用流式字节,您可以将其转到END
,这意味着您找到了匹配的字词,您应该丢弃它。如果没有,这个词是唯一的,不需要删除。如果发现唯一,则必须将该词添加到树结构中以丢弃其进一步重复。
树结构会占用大量内存,但无论如何都不会在某种数组中保存唯一的单词
答案 2 :(得分:0)
有许多可能的优化。
正如Roman Saveljev所说,你可以在记忆中保留一个特里结构。根据数据的熵,它可以很容易地适应内存。
当第二个文件已排序时,您可以运行二进制搜索以检查记录是否存在(如果您还没有这样做)。
您还可以在内存中保留Bloom Filter,以便轻松检查那些不重复的记录,以避免每次都进入磁盘。