How to Find If a Given Key Exists in a C++ Std::Map

How to find if a given key exists in a C++ std::map

Use map::find and map::end:

if (m.find("f") == m.end()) {
// not found
} else {
// found
}

Determine if map contains a value for a key?

Does something along these lines exist?

No. With the stl map class, you use ::find() to search the map, and compare the returned iterator to std::map::end()

so

map<int,Bar>::iterator it = m.find('2');
Bar b3;
if(it != m.end())
{
//element found;
b3 = it->second;
}

Obviously you can write your own getValue() routine if you want (also in C++, there is no reason to use out), but I would suspect that once you get the hang of using std::map::find() you won't want to waste your time.

Also your code is slightly wrong:

m.find('2'); will search the map for a keyvalue that is '2'. IIRC the C++ compiler will implicitly convert '2' to an int, which results in the numeric value for the ASCII code for '2' which is not what you want.

Since your keytype in this example is int you want to search like this: m.find(2);

checking if key exist in map then updating value

else if ( it == two.end() ) 
{
it->second = it->second + 1.0;

Above line of code need to correct as follows

else if ( it != two.end() ) 
^^^
{
it->second = it->second + 1.0;

More than that:

it = two.find(string(pairs[i]) );

Above line can rewrite as follows

it = two.find(pairs[i] );

How to check if a value exists within a C++ Map

valueFinder is just an iterator for the type std::map<int,int> that is not associated to any instance of that type.

To associate it to an instance (here fibonacci_storage) you have to assign it to that instance, i.e.

valueFinder = fibonacci_storage.begin();

Finding an element can be done with source

valueFinder = fibonacci_storage.find(value);

where value is the key you are searching for. Now you check if value is in the map:

if( valueFinder != fibonacci_storage.end() )
{
// value found
}

and you're done.

How to find an element in std::map with structures that has at least one data member equal to the key

std::map is defined only in terms of the operator<. Two map entries are considered equal if and only if !(a < b) and !(b < a). Your operator== is not helping here, and all the find() call is doing is finding the person with the ID you specified (or name in the second case) because it only considers operator<.

The bigger picture is that std::map::find makes use of the sortedness of std::map (generally implemented as a red black tree) to avoid having to check each element. This property is not helpful if both name and ID participate in your search, because you can't tell if a matching name or is before or after any given node in the tree - you only know that for the ID (or, in the second case, the name).

Unless you want to implement a very fancy and complex way of combining the name and ID into a single sortable/searchable field (no idea how you would do that), you will have to check each element. std::find_if does that for you:

std::find_if(phonebook.begin(), phonebook.end(), [name, id](const std::pair<Person, std::string>& personAndNumber) {
const Person& person = personAndNumber.first;
return person.name == name || person.id == id;
});

Searching std::map in O(n) for a partial key

In c++14 you can use the overload to search on a partial key:

struct CompareFirstTwo {
using is_transparent = void;
bool operator()(const tuple<A, B, C>& lhs, const tuple<A, B, C>& rhs) const ...
bool operator()(const tuple<A, B>& lhs, const tuple<A, B, C>& rhs) const ...
bool operator()(const tuple<A, B, C>& lhs, const tuple<A, B>& rhs) const ...
};

Use the comparator above in a call to equal_range to ignore the third field in the tuple.

How to retrieve all keys (or values) from a std::map and put them into a vector?

While your solution should work, it can be difficult to read depending on the skill level of your fellow programmers. Additionally, it moves functionality away from the call site. Which can make maintenance a little more difficult.

I'm not sure if your goal is to get the keys into a vector or print them to cout so I'm doing both. You may try something like this:

std::map<int, int> m;
std::vector<int> key, value;
for(std::map<int,int>::iterator it = m.begin(); it != m.end(); ++it) {
key.push_back(it->first);
value.push_back(it->second);
std::cout << "Key: " << it->first << std::endl();
std::cout << "Value: " << it->second << std::endl();
}

Or even simpler, if you are using Boost:

map<int,int> m;
pair<int,int> me; // what a map<int, int> is made of
vector<int> v;
BOOST_FOREACH(me, m) {
v.push_back(me.first);
cout << me.first << "\n";
}

Personally, I like the BOOST_FOREACH version because there is less typing and it is very explicit about what it is doing.

Cannot find a key of a std::map with customized compare function

Given two elements a and b the comparator is used to decide if a should come before b. If comp(a,b) == true then a comes before b.

The same element cannot be placed before itself. Though, your comparator requires that, because mycomp(a,a) == true.

More specifically the comparator must impose a strict weak ordering. The constraints are listed here: https://en.cppreference.com/w/cpp/named_req/Compare

It says:

  • For all a, comp(a,a)==false
  • If comp(a,b)==true then comp(b,a)==false
  • if comp(a,b)==true and comp(b,c)==true then comp(a,c)==true

Your comparator violates the first two. Note that the comparator and sorting do not care at all about equality. Certainly a==a, but even if this was not the case (because your elements have some odd operator==) comp(a,a) must return false.

Using a comparator for sort or for a std::map that does not adhere to the requirements listed in the page linked above results in undefined behavior.



Related Topics



Leave a reply



Submit