【问题标题】:Count word frequency of huge text file [duplicate]计算巨大文本文件的词频[重复]
【发布时间】:2013-02-07 08:09:31
【问题描述】:

我有一个巨大的文本文件(大于可用的 RAM 内存)。我需要计算所有单词的频率并将单词和频率计数输出到一个新文件中。结果应按频率计数的降序排序。

我的方法:

  1. 对给定文件进行排序 - 外部排序
  2. 按顺序统计每个单词的出现频率,将计数存储在另一个文件中(与单词一起)
  3. 根据频率计数对输出文件进行排序 - 外部排序。

我想知道是否有更好的方法来做到这一点。我听说过基于磁盘的哈希表吗?或 B+ 树,但以前从未尝试过。

注意:我在 SO 上看到过类似的问题,但没有一个必须解决数据大于内存的问题。

编辑:基于 cmets,一致认为实践中的字典应该适合当今计算机的内存。但是让我们假设一个单词词典,它大到无法放入记忆中。

【问题讨论】:

  • 您正在使用哪种编程语言?
  • 所有不同的单词仍然比 RAM 大吗?
  • 如果只想统计字数,可以逐行读取,也可以按文件流读取。您不需要将整个文件加载到 RAM 中。
  • 文件中有多少个不同的字词?如果您不存储重复项,它们是否适合内存?
  • 真的吗?多少内存?即使是一本完整的字典也适合今天的计算机 RAM...

标签: java algorithm data-structures text-files word-count


【解决方案1】:

我会采用map reduce 方法:

  1. 在节点上分发您的文本文件,假设节点中的每个文本都可以放入 RAM。
  2. 计算节点内的每个词频。 (使用hash tables
  3. 在主节​​点中收集每个结果并将它们全部合并。

【讨论】:

  • 由于发帖人声称文件中使用的单词字典甚至不适合他的小 RAM(???)我对这个解决方案投票 +1 - 当只有一台机器时,这也适用您按顺序进行切片。
  • 我按顺序考虑过这种方法,但是如何有效地组合结果呢?
  • 单独对每个结果文件进行排序,然后将它们全部打开并逐行读取,决定是否添加结果(相同的单词)和/或,根据字母表中的顺序,哪个单词/nr 对写入结果文件。
  • 是的,这几乎就是外部排序所做的。除了我们不需要对整个文件进行排序之外,只需对切片进行排序就足够了。
【解决方案2】:

所有独特的单词可能都适合记忆,所以我会使用这种方法:

  • 创建字典 (HashMap<string, int>)。
  • 逐行读取巨大的文本文件。
  • 将新词添加到字典中并将值设置为 1。
  • 现有单词的值加 1。

解析整个大文件后:

  • 按频率对字典进行排序。
  • 将排序后的字典与单词和频率一起写入新文件。

请注意将单词转换为小写或大写。

【讨论】:

  • 不错的方法。但是你会在每个单词之间对字典进行排序吗?这是否会导致更快地搜索未来的单词?
  • no... 添加所有单词后对字典进行排序。
  • 为什么是Dictionary?该类被标记为过时。
  • @Matteo:我不建议使用 Dictionary 类。除了过时之外,它也是一个抽象类,没有用处。 dictionary 一词的选择取决于 HashMap 的用途。
  • 假设大部分单词不重复。这种方法在读取文件大小为 1 Pebibyte (PiB) 的内容时会正常工作吗?
【解决方案3】:

实现它的最佳方法是逐行读取文件并将单词存储到 Multimap 中(例如Guava)。如果此 Map 扩展了您的记忆,您可以尝试使用键值存储(例如 Berkeley JE DB 或 MapDB)。这些键值存储的工作方式类似于地图,但它们将值存储在 HDD 上。我使用 MapDB 解决了类似的问题,而且速度非常快。

【讨论】:

  • 酷,我试试看。
【解决方案4】:

如果唯一单词列表和频率适合内存(不是文件只是唯一单词),您可以使用哈希表并顺序读取文件(不存储它)。

然后您可以按出现次数对哈希表的条目进行排序。

【讨论】:

    猜你喜欢
    • 2016-01-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-11
    • 2013-12-09
    • 1970-01-01
    相关资源
    最近更新 更多