【问题标题】:Why Trie DataStructure when Dictionary Class can be used for string count from large files为什么字典类可用于大文件中的字符串计数时尝试 DataStructure
【发布时间】:2014-10-26 03:07:04
【问题描述】:

假设我需要统计一个非常大的文件中的单词(单词被 " " 分割)

我会关注

  1. 不在内存中加载整个文件,逐行读取流。
  2. 对于每一行拆分单词并将不同的单词添加到“字典”(我的意思是,使用字典类 在 .NET 中) 的数量。

现在要检索最常用的单词,对字典进行排序并获取它。

但大多数解决方案都支持 Trie 数据结构,请说明原因(另外,如果不说明字典上的哈希表的原因,那就太好了)。

谢谢。

【问题讨论】:

  • 究竟是什么意思非常大
  • “为什么不在字典上散列表”:Dictionary<K,V> 散列表;它与Hashtable 类基本相同,只是它是通用的。
  • 你自己试试吧。当您查询“c# trie class”时,您会从 Google 获得大量帮助。当您将它与 Linq 查询或字典进行比较时,您会发现了解现代计算机的工作方式非常非常重要的东西。并且能够提出一个很好的问题。

标签: c# .net data-structures hashtable idictionary


【解决方案1】:

您可以使用类似于流阅读器的File.ReadLines

var mostFrequent = File.ReadLines("Path")
    .SelectMany(l => l.Split()) // splits also by tabs
    .GroupBy(word => word)
    .OrderByDescending(g => g.Count())
    .First(); // or Take(10) if you want the top 10

Console.Write("Word:{0} Count:{1}", mostFrequent.Key, mostFrequent.Count());

【讨论】:

  • @ThomasLevesque:“现在要检索最常用的词,对字典进行排序并获取它。” 我不明白他为什么需要字典,如果他只想找到最常见的单词+计数。
  • 非常大,我的意思是一个 TB 文件或 10 TB 或更多
  • @TimSchmelter,我指的是那部分:“但大多数解决方案都支持 Trie 数据结构,请说明原因”
  • 不只是一个词,假设我想要 10 个最常用的词
  • @ThomasLevesque:我认为他指的是这样的解决方案:stackoverflow.com/questions/12190326/… 对于这么大的文件,我的方法是不可接受的,但是,我为需要简单方法的人保留它。
【解决方案2】:

我不得不提一下,这不仅是一个 map-reduce 问题,还是the map-reduce problem

除此之外,您使用 trie 实现的原因是为了提高查找每个单词以增加其计数的效率(或添加一个在 trie 中尚不存在的单词)。在基本的 trie 中,每个单词的查找时间是 O(n),其中 n 是单词中的字符数。在整个文档中,如果没有并行处理,您将只查看 O(n) 时间以进行查找,其中 n 是文档中的字符数。然后,将(可能)进行深度优先搜索以检索所有单词,以便您可以提取所需的信息。深度优先搜索的最坏情况性能与O(n) 相同,但由于有共同前缀,预期情况会更好。

如果您使用涉及哈希查找的不同结构,例如标准System.Collections.Generic.Dictionary<TKey, TValue>,则成本与哈希查找和实现以及哈希冲突的普遍性有关。然而,即使这可能不是成本的主要部分。假设 arguendo 散列查找是恒定时间且微不足道的。因为相等的哈希码不保证字符串相等,如the MSDN docs warn repeatedly,仍然需要比较字符串是否相等,这几乎可以肯定实现为O(n),其中n 是字符数(为简单起见)。因此,根据 trie 和一些基于哈希查找的字典的实现,基于哈希查找的字典可能并不比 trie 好,甚至可能更差。

对我的分析的一个有效批评可能是对 trie 中每个节点的查找可能不是恒定时间的;这将取决于用于确定后续节点边缘的集合。但是,如果我们不关心以后对键进行排序,那么基于哈希查找的字典可能会在这里工作得很好。当输入是一个字符时,哈希冲突不太可能发生,并且与完整字符串相比,相等比较涉及的内容要少得多。插入性能也可能是合理的,同样取决于实现。

但是,如果您知道要根据字数确定最热门的 n 字数,则您可能需要随时跟踪最热门的 n 字数在 trie 中跟踪它们。这样,您无需在填充 trie 后重新计算顶部的 n

【讨论】:

  • 这也是关于内存消耗的。将 very 大文件中的单词保存在 trie 中所需的时间要少得多。在单词的每个变体的哈希图中,您将拥有另一条记录。但在尝试中,您将重用已经存在的单词部分。
  • 您的“map-reduce 问题”链接已损坏。此页面上的内容可能具有可比性,但我真的不知道,从未看过原版。 hadoop.apache.org/docs/r2.9.1/hadoop-mapreduce-client/…
  • @bielawski 是的,该链接似乎是等效的,尽管旧链接在 archive.org 上。我会编辑。
猜你喜欢
  • 2021-12-31
  • 2011-12-06
  • 1970-01-01
  • 1970-01-01
  • 2015-05-28
  • 2021-12-25
  • 2020-09-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多