WIth std::map<Key, Value>, I can get a value if I have a key, but not vice versa.
I need a map that can do both. Is there one that can do this?
Posted 21 January 2013 - 10:07 PM
Posted 21 January 2013 - 10:53 PM
You could probably do a std::vector<std::pair<Key1, Key2>>, and use std::find_if(), with the predicate checking only first or only second of the pair element, returning a match for either one. It wouldn't be sorted for rapid searches, though.
But now that I think about it, you could just do std::find_if() on a std::map when you need by-value lookups, if you don't need it frequently.
You could either use a lambda to do your search, if you use C++11, or you could use a functor like this:
template<typename KeyType, typename ValueType>
class SearchByValue
{
public:
SearchByValue(ValueType value) : value(value)
{ }
bool operator()(const std::pair<KeyType, ValueType> &pair)
{
//Return true if the pair's value matches our value.
return (pair.second == this->value);
}
private:
ValueType value;
};
int main(int argc, char *argv[])
{
typedef std::map<std::string, int>::iterator MyMapIterator;
std::map<std::string, int> myMap;
myMap["One"] = 1;
myMap["Two"] = 2;
myMap["Three"] = 3;
MyMapIterator it = std::find_if(myMap.begin(), myMap.end(), SearchByValue<std::string, int>(2));
if(it == myMap.end())
{
std::cout << "Couldn't find it!" << std::endl;
}
else
{
std::cout << "The returned key-value pair is: (\"" << it->first << "\", " << it->second << ")" << std::endl;
}
return 0;
}
Result: The returned key-value pair is: ("Two", 2)
The templated functor I gave should work for most maps.
All glory be to the Man at the right hand... On David's throne the King will reign, and the Government will rest upon His shoulders. All the earth will see the salvation of God.
Of Stranger Flames - [indie turn-based rpg set in a para-historical French colony] | Indie RPG development journal
Posted 21 January 2013 - 11:25 PM
Here's a function wrapping it up every nicer (still avoiding C++11 lambda and auto, just incase you can't use them):
/*
A functor for doing a reverse value-to-key lookup on a map.
Example:
typedef std::map<std::string, int>::iterator MyMapIterator;
std::map<std::string, int> myMap;
myMap["One"] = 1;
myMap["Two"] = 2;
myMap["Three"] = 3;
MyMapIterator it = std::find_if(myMap.begin(), myMap.end(), SearchByValue<std::string, int>(2));
*/
template<typename KeyType, typename ValueType>
class SearchByValue
{
public:
SearchByValue(const ValueType &value) : value(value)
{ }
bool operator()(const std::pair<KeyType, ValueType> &pair)
{
//Return true if the pair's value matches our value.
return (pair.second == this->value);
}
private:
ValueType value;
};
//Searches a map by value to find the key.
//Example usage:
// std::string key = SearchMapByValue(map, 357 /* value */, "fallback");
template<typename MapType>
const typename MapType::key_type &SearchMapByValue(const MapType &map, const typename MapType::mapped_type &valueToFind,
const typename MapType::key_type &fallback = typename MapType::key_type())
{
typename MapType::const_iterator it = std::find_if(map.begin(), map.end(), SearchByValue<typename MapType::key_type, typename MapType::mapped_type>(valueToFind));
if(it == map.end())
return fallback;
return it->first;
}
And you can use it as a simple function call, and all the templated types are automaticly detected by the map passed in:
std::map<std::string, int> myMap; myMap["One"] = 1; myMap["Two"] = 2; myMap["Three"] = 3; std::cout << "The key is: \"" << SearchMapByValue(myMap, 2) << "\"" << std::endl;
Result: The key is: "Two"
Put in a stand-alone header file, all you have to do is call SearchMapByValue(myMap, 2) or SearchMapByValue(myMap, 2, "fallback") and it'll "just work" with any variable type in a map that handles equality. (Searching for floats wouldn't be a good idea, but even some complex classes that have operator == would be fine)
All glory be to the Man at the right hand... On David's throne the King will reign, and the Government will rest upon His shoulders. All the earth will see the salvation of God.
Of Stranger Flames - [indie turn-based rpg set in a para-historical French colony] | Indie RPG development journal