Значение проверки существует в std:: map-c++
Я знаю найти метод находит поставляемый ключ в std:: map и возвращает итератор на элемент. Есть ли в любом случае, чтобы найти значение и получить итератор для элемента? Что мне нужно сделать, так это проверить указанное значение в std:: map. Я сделал это, зациклив все элементы на карте и сравнивая. Но я хотел бы знать, есть ли лучший подход для этого.
вот что у меня написал
bool ContainsValue(Type_ value)
{
bool found = false;
Map_::iterator it = internalMap.begin(); // internalMap is std::map
while(it != internalMap.end())
{
found = (it->second == value);
if(found)
break;
++it;
}
return found;
}
редактировать
Как насчет использования другой карты внутри, которая хранит значение, комбинацию клавиш. Чтобы я мог позвонить в find? Is найти() в std:: map делает последовательный поиск?
спасибо
9 ответов
можно использовать boost:: multi_index создать двунаправленный карте - вы можете использовать любое значение пары в качестве ключа для быстрого поиска.
Если у вас есть доступ к отличному boost библиотека, то вы должны использовать boost:: multi_index создать двунаправленный карте как говорит Марк. В отличие от std:: map это позволяет искать либо по ключу, либо по значению.
Если у вас есть только STL, чтобы передать следующий код, сделает трюк (шаблонный для работы с любой картой, где mapped_type поддерживает operator==):
#include <map>
#include <string>
#include <algorithm>
#include <iostream>
#include <cassert>
template<class T>
struct map_data_compare : public std::binary_function<typename T::value_type,
typename T::mapped_type,
bool>
{
public:
bool operator() (typename T::value_type &pair,
typename T::mapped_type i) const
{
return pair.second == i;
}
};
int main()
{
typedef std::map<std::string, int> mapType;
mapType map;
map["a"] = 1;
map["b"] = 2;
map["c"] = 3;
map["d"] = 4;
map["e"] = 5;
const int value = 3;
std::map<std::string, int>::iterator it = std::find_if( map.begin(), map.end(), std::bind2nd(map_data_compare<mapType>(), value) );
if ( it != map.end() )
{
assert( value == it->second);
std::cout << "Found index:" << it->first << " for value:" << it->second << std::endl;
}
else
{
std::cout << "Did not find index for value:" << value << std::endl;
}
}
Как насчет использования другой карты внутри, которая хранит значение, комбинацию клавиш. Чтобы я мог позвонить в find?
да: поддерживайте две карты, причем одна карта использует один тип ключа, а другая-другой.
is find () в std::map выполняет последовательный поиск?
нет это двоичный поиск отсортированного дерева: его скорость равна O(log (n)).
посмотрите на двунаправленные карты boost:http://www.boost.org/doc/libs/1_38_0/libs/bimap/doc/html/index.html
Это позволяет обоим значениям действовать как ключ.
в противном случае итерация-это путь.
попробуйте эту функцию:
template <class Map, class Val> typename Map::const_iterator MapSearchByValue(const Map & SearchMap, const Val & SearchVal)
{
Map::const_iterator iRet = SearchMap.end();
for (Map::const_iterator iTer = SearchMap.begin(); iTer != SearchMap.end(); iTer ++)
{
if (iTer->second == SearchVal)
{
iRet = iTer;
break;
}
}
return iRet;
}
Я думаю, что это полезно
нет, вы должны зациклиться на std:: map и проверить все значения вручную. В зависимости от того, что вы хотите сделать, вы можете обернуть std::map в простой класс, который также кэширует все значения, вставленные в карту, в чем-то, что легко найти и не позволяет дубликаты, например std::set. Не наследуйте от std:: map (у него нет виртуального деструктора!), но оберните его так, чтобы вы могли сделать что-то вроде этого:
WrappedMap my_map< std::string, double >;
my_map[ "key" ] = 99.0;
std::set< double > values = my_map.values(); // should give back a set with only 99.0 in it
альтернатива к свертывать ваш собственный было бы использовать двунаправленную карту Boost, которую легко найти в сообщениях ниже или Google.
это действительно зависит от того, что вы хотите сделать, как часто вы хотите это сделать, и как трудно свернуть свой собственный маленький класс обертки против установки и использования Boost. Я люблю Boost, так что это хороший способ пойти - но есть что-то хорошее и полное в создании собственного класса обертки. У вас есть преимущество в понимании непосредственно сложности операций, и вы не можете требуется полное обратное сопоставление значений => ключей, которое предоставляется двунаправленной картой Boost.
то, что вы запрашиваете, именно то, что std:: find делает (не функция-член)
template< class InputIt, class T >
InputIt find( InputIt first, InputIt last, const T& value );
Не самый лучший вариант, но может быть полезен в нескольких случаях, когда пользователь назначает значение по умолчанию, такое как 0 или NULL при инициализации.
Ex.
< int , string >
< string , int >
< string , string >
consider < string , string >
mymap["1st"]="first";
mymap["second"]="";
for (std::map<string,string>::iterator it=mymap.begin(); it!=mymap.end(); ++it)
{
if ( it->second =="" )
continue;
}
возможно, я не совсем понимаю, чего вы пытаетесь достичь. Но чтобы просто проверить, содержит ли карта значение, я считаю, что вы можете использовать std::map
построены в find
.
bool ContainsValue(Type_ value)
{
return (internalMap.find(value) != internalMap.end());
}