是否有更惯用的方法将 "insert or accumulate" 转换为 unordered_map 表示项目计数?
Is there a more idiomatic way to "insert or accumulate" into an unordered_map representing item counts?
考虑如下代码:
#include <iostream>
#include <unordered_map>
std::unordered_map<char, int> get_letter_frequencies(const std::string& str) {
std::unordered_map<char, int> freqs;
for (char ch : str) {
auto iter = freqs.find(ch);
if (iter == freqs.end()) {
freqs[ch] = 1;
} else {
iter->second++;
}
}
return freqs;
}
int main()
{
std::string str = "AABBDBCABDA";
auto freqs = get_letter_frequencies(str);
std::cout << freqs['B'] << "\n";
return 0;
}
将字母数存储在 unordered_map 中。我的问题是是否有一段 terser/more 惯用代码可以用来替换
auto iter = freqs.find(ch);
if (iter == freqs.end()) {
freqs[ch] = 1;
} else {
iter->second++;
}
我可以写一个函数 insert_or_accumulate( ... )
但它看起来有点过分了。
就这样:
for (char ch : str) {
++freqs[ch];
}
只需访问 freqs[ch]
即可创建键值对(如果缺少),使用默认构造函数(对于 int
,这使得 0
)和 returns对值(新的或现有的)的引用,因此 ++freqs[ch]
将增加现有值,同时创建和增加缺失值。
注意:我偏好使用前缀 ++
;这在这里无关紧要,因为我们正在递增原始内置类型,但在 C++ 中,您希望养成默认使用前缀递增的习惯,因为 类 重载递增 不能 像前缀增量一样有效地实现后缀增量(后缀需要制作实例的副本,前缀可以在没有副本的情况下运行)。
考虑到动态分配和散列的数量,使用 std::unordered_map
本身有点矫枉过正。当然,迭代非零元素既快速又容易,但是计算字符的更简单方法是使用一个包含 256 个值的简单数组。
数组更简单,而且很可能更快,但代价是 可能 如果您想这样做的话,可能会更麻烦地遍历项目。但是,考虑到 unordered_map
会发生的间接性,我个人仍然更喜欢这种方法。也订了。
int freqs[256] = {};
for (unsigned char c : str) ++freqs[ch];
作为 returns 值的函数的插入,您可以使用 std::array
.
#include <array>
#include <string>
#include <iostream>
typedef std::array<int, 256> CharFreqType;
CharFreqType get_letter_frequencies(const std::string& str)
{
CharFreqType freqs{};
for (unsigned char c : str) ++freqs[c];
return freqs;
}
int main()
{
auto freqs = get_letter_frequencies("AABBDBCABDA");
std::cout << freqs['B'] << "\n";
}
考虑如下代码:
#include <iostream>
#include <unordered_map>
std::unordered_map<char, int> get_letter_frequencies(const std::string& str) {
std::unordered_map<char, int> freqs;
for (char ch : str) {
auto iter = freqs.find(ch);
if (iter == freqs.end()) {
freqs[ch] = 1;
} else {
iter->second++;
}
}
return freqs;
}
int main()
{
std::string str = "AABBDBCABDA";
auto freqs = get_letter_frequencies(str);
std::cout << freqs['B'] << "\n";
return 0;
}
将字母数存储在 unordered_map 中。我的问题是是否有一段 terser/more 惯用代码可以用来替换
auto iter = freqs.find(ch);
if (iter == freqs.end()) {
freqs[ch] = 1;
} else {
iter->second++;
}
我可以写一个函数 insert_or_accumulate( ... )
但它看起来有点过分了。
就这样:
for (char ch : str) {
++freqs[ch];
}
只需访问 freqs[ch]
即可创建键值对(如果缺少),使用默认构造函数(对于 int
,这使得 0
)和 returns对值(新的或现有的)的引用,因此 ++freqs[ch]
将增加现有值,同时创建和增加缺失值。
注意:我偏好使用前缀 ++
;这在这里无关紧要,因为我们正在递增原始内置类型,但在 C++ 中,您希望养成默认使用前缀递增的习惯,因为 类 重载递增 不能 像前缀增量一样有效地实现后缀增量(后缀需要制作实例的副本,前缀可以在没有副本的情况下运行)。
考虑到动态分配和散列的数量,使用 std::unordered_map
本身有点矫枉过正。当然,迭代非零元素既快速又容易,但是计算字符的更简单方法是使用一个包含 256 个值的简单数组。
数组更简单,而且很可能更快,但代价是 可能 如果您想这样做的话,可能会更麻烦地遍历项目。但是,考虑到 unordered_map
会发生的间接性,我个人仍然更喜欢这种方法。也订了。
int freqs[256] = {};
for (unsigned char c : str) ++freqs[ch];
作为 returns 值的函数的插入,您可以使用 std::array
.
#include <array>
#include <string>
#include <iostream>
typedef std::array<int, 256> CharFreqType;
CharFreqType get_letter_frequencies(const std::string& str)
{
CharFreqType freqs{};
for (unsigned char c : str) ++freqs[c];
return freqs;
}
int main()
{
auto freqs = get_letter_frequencies("AABBDBCABDA");
std::cout << freqs['B'] << "\n";
}