C++ 计数图
C++ Counting Map
最近我在处理我确定是一个非常普遍的问题,基本上可以归结为以下几点:
给定一个长文本,计算每个单词在文本中出现的频率。
我能够使用 std::unordered_map
解决这个问题。然而,这变得非常难看,对于文本中的每个单词,如果已经遇到过,我必须进行查找、删除,然后重新插入地图并增加值。
我知道还有其他方法可以做到这一点,例如在原始 array/vector 之上使用散列函数并在那里增加值,但我想知道是否有更优雅的方法来解决这个问题问题,如 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];
不需要任何类型的find/erase/reinsert。
如果不清楚 how/why 这有效:如果 none 还存在于地图中,operator[]
将为一个值创建一个条目。关联值将是指定类型的值初始化对象,在 int
(或类似)的情况下将为零。然后我们每次遇到这个词时都会增加它。
另一种解决方案:
std::multiset<std::string> m;
for (auto w: words) m.insert(w);
m.count("some word");
优点是不用依赖'trick'和operator[]
,代码可读性更好。
EDIT:正如 Kerrek 在评论中指出的那样,此解决方案速度较慢。 multiset
存储您插入的所有元素,即使它们被认为是相等的(它们可能在 operator==
未检查的某些方面仍然不同)。与 unordered_map<std::string, int>
相比,这会导致显着的开销,后者只需将每个单词存储一次。
(附带说明,在我的机器上使用地图解决方案处理莎士比亚全集大约需要 0.33 秒,而使用多集解决方案则需要 0.78 秒。)
最近我在处理我确定是一个非常普遍的问题,基本上可以归结为以下几点:
给定一个长文本,计算每个单词在文本中出现的频率。
我能够使用 std::unordered_map
解决这个问题。然而,这变得非常难看,对于文本中的每个单词,如果已经遇到过,我必须进行查找、删除,然后重新插入地图并增加值。
我知道还有其他方法可以做到这一点,例如在原始 array/vector 之上使用散列函数并在那里增加值,但我想知道是否有更优雅的方法来解决这个问题问题,如 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];
不需要任何类型的find/erase/reinsert。
如果不清楚 how/why 这有效:如果 none 还存在于地图中,operator[]
将为一个值创建一个条目。关联值将是指定类型的值初始化对象,在 int
(或类似)的情况下将为零。然后我们每次遇到这个词时都会增加它。
另一种解决方案:
std::multiset<std::string> m;
for (auto w: words) m.insert(w);
m.count("some word");
优点是不用依赖'trick'和operator[]
,代码可读性更好。
EDIT:正如 Kerrek 在评论中指出的那样,此解决方案速度较慢。 multiset
存储您插入的所有元素,即使它们被认为是相等的(它们可能在 operator==
未检查的某些方面仍然不同)。与 unordered_map<std::string, int>
相比,这会导致显着的开销,后者只需将每个单词存储一次。
(附带说明,在我的机器上使用地图解决方案处理莎士比亚全集大约需要 0.33 秒,而使用多集解决方案则需要 0.78 秒。)