C++计数地图

C++ Counting Map

本文关键字:地图 C++      更新时间:2023-10-16

最近我正在处理一个我确信是一个非常普遍的问题,它基本上归结为以下内容:

给定一个长文本,计算文本中每个单词出现的频率。

我能够使用std::unordered_map解决这个问题。然而,这变得非常丑陋,因为文本中的每个单词,如果已经遇到这种情况,我必须进行查找,擦除,然后重新插入到地图中,并增加值。

我意识到还有其他方法可以做到这一点,例如在香草数组/向量之上使用哈希函数并在那里增加值,但我想知道是否有更优雅的方法来解决这个问题,比如 STL 组件或函数。 这将具有与Pythons Counter 集合类似的接口。

我知道C++C++我真的不能指望总是为我实现如此高级的概念,但只是想知道你们是否对任何事情都很陌生(或者至少你的谷歌搜索技能优于我的(,这可能会让我的代码更好一点。

我不太确定为什么std::unordered_map(或只是std::map(会涉及很多复杂性。我会写这样的代码:

std::unordered_map<std::string, int> words;
std::string word;
while (word = getword(input))
   ++words[word];

无需任何类型的查找/擦除/重新插入。

如果不清楚如何

/为什么这样做:如果映射中尚不存在值,operator[]将为值创建一个条目。关联的值将是指定类型的值初始化对象,如果是int(或类似值(,则为零。然后,每次遇到这个词时,我们都会增加它。

另一种解决方案:

std::multiset<std::string> m;
for (auto w: words) m.insert(w);
m.count("some word");

优点是你不必依赖operator[]的"技巧",使代码更具可读性。

编辑:正如Kerrek在评论中指出的那样,这种解决方案较慢。 multiset存储您插入的所有元素,即使它们被视为相等(它们在某些方面可能仍然不同,operator==不会检查(。与unordered_map<std::string, int>相比,这会导致大量的开销,因为只需要存储每个单词一次。

(作为旁注,使用映射解决方案处理威廉·莎士比亚的全部作品在我的机器上大约需要 0.33 秒,而多集解决方案需要 0.78 秒。