如何在unordered_map中设置一个值,并确定是否添加了新的密钥 [英] How to set a value in an unordered_map and find out if a new key was added

查看:410
本文介绍了如何在unordered_map中设置一个值,并确定是否添加了新的密钥的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我如何在 unordered_map 中高效并惯用地设置一个值,以确定是否添加了新的密钥:

b
$ b

  #include< unordered_map> 
#include< string>

int main(){
auto map = std :: unordered_map< std :: string,int> {{foo,1},{bar,2}};

map [foo] = 3;
//如何找出是否添加了新密钥?
}

我不能使用 insert() code>,因为如果已经有一个值,并且 insert 没有这样做,我想覆盖该值。我不能直接使用 operator [] ,因为它没有提供关于是否添加新密钥的信息。



我想在性能上避免在地图上进行两次搜索。



我在别处看到的一个技巧是获取引用并检查该值是否为默认构造:

  auto& value = map [foo]; 
if(value == 0){
//正在插入一个新键
}
value = 3;

但我真的可以在我的地图中使用默认的构造值,所以默认的构造值并不是一个好的指示新密钥。



到目前为止我所能想到的最好的是:

  auto size_before = map.size(); 
map [foo] = 3;
if(map.size()> size_before){
//正在插入一个新键
}

这看起来很丑,它假设获得 unordered_map 的大小很便宜(是吗?)。



它看起来像 unordered_map :: insert_or_assign 可能是我祈祷的答案,但遗憾的是它出现在C ++ 17中,所以我可能无法再使用它5年左右。这似乎是相当普遍的事情要这样做,我假设目前必须有一个合理的方式。

解决方案

您可以使用 std :: unordered_map :: insert 和测试结果。



使用辅助函数:

 模板< 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){
//覆盖以前的值
p.first-> second = t;
}
return p;
}

然后

  auto p = insert_or_assign(map,foo,3); 
if(p.second){
//插入
} else {
//分配
}

实时演示


How can I efficiently and idiomatically set a value in an unordered_map and find out if a new key was added:

#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?
}

I can't use insert() directly because I want to overwrite the value if there is one already and insert does not do that. I can't use operator[] directly because it provides no information about whether a new key was added.

I want to avoid doing two searches in the map for performance reasons.

One trick I've seen elsewhere is to get a reference and check if that value is default constructed:

auto& value = map["foo"];
if(value == 0) {
    // am inserting a new key
}
value = 3;

But I can genuinely have default constructed values in my map so a default constructed value is not a good indication of new key.

The best I can come up with so far is:

auto size_before = map.size();
map["foo"] = 3;
if (map.size() > size_before) {
    // am inserting a new key
}

which seems ugly and it assumes that getting the size of an unordered_map is cheap (is it?).

It looks like unordered_map::insert_or_assign might be the answer to my prayers but sadly it comes in C++17 so I probably wont be able to use it for another 5 years or so. It seems like quite a common thing to want to do so I assume there must be a reasonable way of doing it currently.

解决方案

You may use std::unordered_map::insert and testing result.

With helper function:

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;
}

and then

auto p = insert_or_assign(map, "foo", 3);
if (p.second) {
    // inserted
} else {
    // assigned
}

Live Demo

这篇关于如何在unordered_map中设置一个值,并确定是否添加了新的密钥的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆