0

我必须有 2 个 utf-8 文本文件。在文件的每一行中都有一个字符串,可以包含语言特定的字符,如 Ü、Ö、ą、ę。字符串是随机的顺序和长度,并且可以重复。在第一个文件中至少有 300 万行(很容易超过 1 mld 行)。第二个文件较小,它通常有大约 40 万行(但可以更大)。

我需要创建一个新文件,其中包含文件一中的条目,其中删除了出现在文件二中的条目以及所有重复条目。

目前我正在对两个文件进行排序并删除重复条目。接下来我将它们写入新文件,同时检查它们是否出现在第二个文件中。

有没有更快的方法来做到这一点?

编辑

内存是个问题。我不会将此字符串复制到内存中,而是对文件进行操作。我的朋友建议不要复制到内存,而是处理文件流。在此之后执行时间显着下降。

计算机管理员不想在其上安装数据库。

在循环中对我的代码符文进行排序后:

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
4

3 回答 3

0

有许多可能的优化。

正如 Roman Saveljev 建议的那样,您可以在内存中保留一个 trie 结构。根据数据的熵,它可以很容易地放入内存中。

在对第二个文件进行排序后,您可以运行二进制搜索来检查记录是否存在(如果您还没有这样做)。

您还可以在内存中保留一个布隆过滤器,以便轻松检查那些不重复的记录,以避免每次都进入磁盘。

于 2012-08-03T18:54:46.500 回答
0

如果您有可用的数据结构(例如哈希集),则可以遍历文件并添加每一行。集合不允许重复,hashset应该为您提供一种检查元素是否已经存在的常量方法(至少在 Java 中,该add方法检查元素是否存在,如果不存在,它将项目添加到常量集合中时间)。

浏览完这两个文件后,您就可以遍历哈希集并将其内容存储到文件中。这应该为您提供一种可以在线性时间内完成的算法。

忘了提:我假设您对内存消耗没有限制。如果这样做,您可能想尝试将每一行保存到数据库中,使用每行的哈希作为主键。插入具有两个主键的元素应该会失败,从而确保您在数据库中具有唯一的字符串。完成插入后,您可以检索数据库中的值并将其存储到文件中。

于 2012-08-03T07:34:18.387 回答
0

我的建议是预处理文件二并从中形成树形结构。例如,假设您有这种文件二:

bad
bass
absent

那么你的树结构将是这样的:

BEGIN -> b -> a -> d -> END
|             |
|             + -> s -> s -> END
|
+-> a -> b -> s -> e -> n -> t -> END

END指定单词分隔符(无论是空格还是换行符或其他)

然后您将文件一打开到文件流中并逐字节读取。一旦你遇到文件的开头或在分隔符后选择下一个字符,你就开始走你的树。如果使用流式字节,您可以将其带到END,这意味着您找到了匹配的单词,您应该丢弃它。如果不是,则该词是唯一的,无需删除。如果发现是唯一的,则必须将单词添加到树结构中以丢弃其进一步的重复。

树结构将占用大量内存,但无论如何它都比在某种数组中保存唯一单词要少

于 2012-08-03T08:26:49.857 回答