Reputation: 2635
I have a map
with <int, int*>
I want to search the map
for a specific value (not key) and retrieve the iterator that points to the correct int*
(value of the map)
Can I use the std::find_if()
?
auto it = std::find_if(map.begin(), map.end(), compare);
where the compare should be something like:
bool compare(int* v1, int* v2)
{
return (v1==v2);
}
What is the best way to acomplish this?
Upvotes: 0
Views: 194
Reputation: 16765
You can do it like this:
#include <string>
#include <iostream>
#include <algorithm>
#include <map>
int main()
{
std::map<int, std::string> m = {{1, "a"}, {2, "b"}};
std::string value_to_find = "b";
auto it = std::find_if(m.begin(), m.end(), [&](decltype(m)::value_type &v) {
return v.second == value_to_find;
});
if (it != m.end()) {
std::cout << it->first << std::endl;
}
return 0;
}
Instead of decltype()
you may directly use template instance:
[&](std::map<int, std::string>::value_type &v)
Upvotes: 3
Reputation: 8451
std::find_if
will do the job for any 'map-like' type, e.g. std::map
or std::unordered_map
. Note the collection does not need to be ordered; anything that defines an InputIterator
(i.e. is 'iterable') will do.
Here is a function that will work for anything 'map-like' (but not 'multimap-like')
template <typename MapType>
typename MapType::const_iterator find_value(const MapType& map, const typename MapType::mapped_type& value)
{
return std::find_if(std::cbegin(map), std::cend(map), [&value] (const auto& p) { return p.second == value; });
}
int main(int argc, const char **argv)
{
std::unordered_map<int, char> map {{0, 'A'}, {1, 'B'}, {2, 'C'}};
char val {'B'};
auto it = find_value(map, val);
if (it != std::cend(map)) std::cout << it->first << std::endl;
return 0;
}
You should be aware that this is a linear-time algorithm (regardless of whether the map is ordered or not), and thus if this is an operation you will be using a lot, you should consider if it would be better to just store the inverse mappings too.
Upvotes: 2