如何在unordered_map中设置值并查明是否添加了新键
How to set a value in an unordered_map and find out if a new key was added
如何高效且习惯地在unordered_map
中设置值并找出是否添加了新键:
#include <unordered_map>
#include <string>
int main() {
auto map = std::unordered_map<std::string, int>{{"foo", 1}, {"bar", 2}};
map["foo"] = 3;
// how to find out if a new key was added?
}
我不能直接使用insert()
,因为如果已经有一个值,我想覆盖该值,而insert
不会这样做。我不能直接使用operator[]
,因为它没有提供有关是否添加了新密钥的信息。
出于性能原因,我想避免在地图中进行两次搜索。
我在其他地方看到的一个技巧是获取引用并检查该值是否是默认构造的:
auto& value = map["foo"];
if(value == 0) {
// am inserting a new key
}
value = 3;
但是我可以在我的地图中真正拥有默认构造的值,因此默认构造值不能很好地指示新键。
到目前为止,我能想到的最好的是:
auto size_before = map.size();
map["foo"] = 3;
if (map.size() > size_before) {
// am inserting a new key
}
这看起来很丑陋,它假设获得unordered_map
的大小很便宜(是吗?
看起来unordered_map::insert_or_assign
可能是我祈祷的答案,但遗憾的是它出现在 C++17 年,所以我可能再过 5 年左右才能使用它。想要这样做似乎是一件很常见的事情,所以我认为目前必须有一种合理的方法来做到这一点。
std::unordered_map::insert
和测试结果。
带辅助功能:
template<typename Map, typename T>
std::pair<typename Map::iterator, bool>
insert_or_assign(Map& m, const typename Map::key_type& k, const T& t)
{
auto p = m.insert({k, t});
if (!p.second) {
// overwrite previous value
p.first->second = t;
}
return p;
}
然后
auto p = insert_or_assign(map, "foo", 3);
if (p.second) {
// inserted
} else {
// assigned
}
现场演示
insert()
成员函数,该函数将返回一个pair
,该函数返回一对,该函数由插入元素(或阻止插入的元素(的迭代器和指示插入是否发生的布尔值组成。 它看起来像
if (map_name.insert(some_value).second)
value was inserted
else
value was not inserted
如果需要在未插入元素时修改映射中的值,则可以使用
auto ret = map_name.insert(some_value);
if (!ret.second)
*(ret.first) = some_value;
编辑:更新
从 C++17 开始,std::map
和std::unordered_map
成员函数insert_or_assign()
。 如果键/值对不在映射中,此函数将插入到容器中,如果键已存在,则此函数将覆盖容器中的现有值。 该函数将返回一个std::pair
,其中包含插入/更新元素的迭代器和布尔信号,指示是否有插入。 如果有插入,那么它将true
否则false
std::unordered_map<std::string, int> foo = { { "foo", 1 },{ "bar", 2 } };
auto ret = foo.insert_or_assign("foo", 3);
if (ret.second)
std::cout << "foo was inserted";
else
std::cout << "foo already exist. new value: " << ret.first->second;
输出:
foo already exist. new value: 3
我目前找不到支持 C++17 的在线编译器,我可以共享代码,但您可以在此处或 Visual Studio 2015 Microsoft运行它
- 添加静态constexpr成员是否会更改结构/类的内存映射
- 是否将std::packaged_task添加到现有线程
- 将常量字符串添加到非常量字符串是否会给出常量字符串
- 这种方式是否可以接受向向量添加unique_ptr?
- 是否通过向封闭对象的地址添加字节偏移量来访问子对象
- 在 Eclipse 中添加库的工作方式是否与在 Visual Studio 中相同?
- MFC 中的窗口消息管理:添加基类调用是否是强制性的?
- 检查数组中是否有字符串中的值,如果没有,则添加它
- 以这种方式初始化的 char 数组是否会自动添加空终止符?
- 是否可以在 for 循环中添加两个浮点数?
- 在迭代期间添加到 std::unordered_set(或 unordered_map)中的元素是否会在迭代期间访问?
- 是否允许向空指针添加零?
- 检测是否在 QTableWidget 中添加或删除了列
- 是否可以使用OpenMP并行化一个列表,该列表可以在每次迭代中添加新元素
- 添加noexcept是否会破坏二进制兼容性
- 弄清楚使用emplace_hint时是否添加了项目
- cin函数是否添加了在输入结束时终止的null
- 如何在unordered_map中设置值并查明是否添加了新键
- AES_cbc_encrypt是否添加填充
- C++11是否添加了C99限制说明符?如果没有,为什么不呢