C ++计算地图

时间:2015-11-28 19:59:33

标签: c++ dictionary counting

最近我处理的是我确信这是一个非常常见的问题,基本上归结为以下几点:

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

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

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

我知道C ++是C ++我真的不能期望总是为我实现这样的高级概念,但只是想知道你们是否有新的东西(或者至少你的谷歌搜索技能优于我的)可能使我的代码更好一点。

2 个答案:

答案 0 :(得分:7)

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

std::unordered_map<std::string, int> words;

std::string word;
while (word = getword(input))
   ++words[word];

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

如果不清楚这是如何/为何如此有效:operator[]将为地图中尚不存在的值创建一个条目。关联值将是指定类型的值初始化对象,在int(或类似)的情况下将为零。然后我们每次遇到这个词时都会增加。

答案 1 :(得分:-1)

另一种解决方案:

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>相比,这会产生很大的开销,只需要将每个单词存储一次。

(作为旁注,使用地图解决方案处理William Shakespeare的全部作品在我的机器上需要大约0.33秒,而多重集解决方案则需要0.78秒。)