Reputation: 182769
I'm looking for an efficient way to do a conditional insert. Ideally, I'd like a template function that would work on any map. I want something like this:
std::map<int, std::string> MyMap;
if(MyMap.ConditionalInsert(3, "Hello"))
{ // there was no element 3, one has been added with value "Hello"
}
else
{ // there was already an element 3 in the map, it's unchanged
}
I can't easily use operator[]
because there's no easy way to tell if it created an element or not. I can use count
for the test, but then I have to search the map twice if we do an insert. I guess something with find
would be best, but it always seems to come out warty and awkward.
Is there a really good way to do this?
Upvotes: 4
Views: 3599
Reputation: 361482
What problem do you see with this:
auto ret = MyMap.insert(std::make_pair(3, "Hello"));
if( ret.second)
{
//the value is inserted
}
else
{
//no value is inserted
}
The return value indicates whether the value is already present or not. If it is not present, the value will be inserted, else no value will be inserted.
Taken from here:
... returns a pair, with its member pair::first set to an iterator pointing to either the newly inserted element or to the element that already had its same value in the map. The pair::second element in the pair is set to true if a new element was inserted or false if an element with the same value existed.
Upvotes: 5
Reputation: 63797
std::map<T1,T2>::insert
already does this check for you, if there already is an entry with the specified key the insert will be aborted.
std::map<int, std::string> m;
m.insert (std::make_pair (3, "hello world"));
m.insert (std::make_pair (3, "world hello"));
std::cerr << m[3] << std::endl;
output:
hello world
std::map<T1,T2>::insert
returns a std::pair<std::map<T1,T2>::iterator, bool>
, the 2nd value (pair.second
) will act as a flag saying if the key/value pair was inserted or not.
if ret.second == true: value was inserted
if ret.second == false: the key has already been set
example snippet:
std::cerr << m.insert (std::make_pair (1,1)).second << std::endl;
std::cerr << m.insert (std::make_pair (1,2)).second << std::endl;
output
1
0
Upvotes: 5
Reputation: 4895
The insert
function already does what you want.
std::pair<std::map<int, std::string>::iterator, bool>
insertionResult = MyMap.insert(std::make_pair(3, "Hello"));
if(insertionResult.second)
{ // there was no element 3, one has been added with value "Hello"
}
else
{ // there was already an element 3 in the map, it's unchanged
}
The first element of the pair gives the location of the element with the key, whether it's old or new.
Upvotes: 1