Check if key exists in std::map

Is there built in functionality for this as a boolean value?
It seems the simplest way is to use find(key) and check to see if it returns map::end?
I think find != end is the way to go.
closed account (EzwRko23)
Ok, I have a similar question, so I post it here.

Very often I encounter such pattern: I want to read value from the map under some key. If the key does not exist, I want to compute a default value (which can be costly, so I do it only when I must), and insert it into map under that key. But: I want it to be efficient - I want to do lookup in the map exactly once, regardless the key existed or not. Is it possible? This is a typical pattern for implementing caches.

Last edited on
Well one thing worth remembering is that std::map::orerator[] will create an element under the given key if one does not already exist. So you can arrange for the map contents to be constructed with a suitable default:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <map>
#include <iostream>

struct data_t
{
	int value;
	data_t(): value(100){} // default value 100
};


int main()
{
	std::map<std::string, data_t> datamap;

	// If key "item" does not exist then a new one is created with value 100
	int value = datamap["item"].value;

	std::cout << "value: " << value << std::endl;
}
EDIT: Galik's solution is much simpler and better. XD

hahahahahaha.

That's what I get for trying to be too creative.

Anyway, I'll leave my original post up because it was fun to do:

____________


lower_bound and insert: It takes some trickery, though. This is the best way I could think to do it:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
template <typename keyT,typename valT>
typename std::map<keyT,valT>::iterator FindOrInsert(std::map<keyT,valT>& mymap,const std::pair<keyT,valT>& insertion)
{
    // if the map is empty, just insert the new value
    if(mymap.empty())
        return mymap.insert(insertion).first;

    // otherwise find the lower_bound
    typename std::map<keyT,valT>::iterator i = mymap.lower_bound( insertion.first );

    // if i == end, or if i is not a match, then this element was not in the map, so we need to insert it
    if(i == mymap.end()  ||  i->first != insertion.first)
    {
        // move i to the element preceeding the insertion point
        if(i != mymap.begin())
            --i;

        // insert it
        i = mymap.insert(i,insertion);
    }

    return i;
}



Usage would be as follows:

1
2
3
4
5
6
7
8
std::map<int,int> mymap;

// fill mymap here

// need to see if mymap has a key of [50].  If not, create the key of [50] with value 25
std::map<int,int>::iterator i = FindOrInsert( mymap, std::pair<int,int>(50,25) );

std::cout << i->first;  // will print '50', as i is pointing to the proper element 
Last edited on
That behaviour corresponds with pair<iterator, bool> map::insert( pair<K, V> ). This way you could use another constructor.

However you still need a public default constructor.
closed account (EzwRko23)
Ok, maybe I forgot to mention that the default value should be based on the key. Otherwise, this would be useless for caching. So, Galik's solution is not what I wanted. Disch solution also suffers from the same problem - the default is computed before checking for presence of the element.

The idea of cache is **not** to compute a value if it can be retrieved from the map.

Last edited on
like this?
1
2
3
4
it_bool = m.insert( pair<K, V> );
   if(it_bool.second){
      magic(it_bool.first->second, etc);
   }


with a very light default constructor, or just modify Disch to
1
2
3
4
it = m.lower_bound(Key);
if(it == m.end() || it->first != Key){
	m.insert(it, pair<K, V>(K,() V(param) )  );
}
closed account (EzwRko23)
Ok, thank you. Now this one is ok, although long and lots of code. I thought this could be done with one single line.
Last edited on
About the original question, see std::map::count:
http://www.cplusplus.com/reference/stl/map/count/
Topic archived. No new replies allowed.