我知道 find 方法在 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()在std :: map中进行顺序搜索吗?
由于
答案 0 :(得分:20)
您可以使用boost::multi_index创建bidirectional map - 您可以使用该对中的任意一个值作为快速查找的键。
答案 1 :(得分:16)
如果您可以访问优秀的boost库,那么您应该使用boost::multi_index创建bidirectional map,如Mark所说。与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;
}
}
答案 2 :(得分:15)
如何在内部使用另一个存储值,键组合的地图。所以我可以打电话找到它吗?
是:维护两张地图,其中一张地图使用一种类型的密钥,另一张使用另一种地图。
std :: map中的find()是否进行顺序搜索?
不,它是对已排序树的二进制搜索:其速度为O(log(n))。
答案 3 :(得分:6)
查看boost的双向地图:http://www.boost.org/doc/libs/1_38_0/libs/bimap/doc/html/index.html
它允许两个值都像键一样。
否则,迭代是可行的方法。
答案 4 :(得分:4)
尝试此功能:
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;
}
我觉得它很有用
答案 5 :(得分:2)
不,你必须遍历std :: map并手动检查所有值。根据你想要做的事情,你可以将std :: map包装在一个简单的类中,该类也可以缓存插入到地图中的所有值,这些值很容易搜索并且不允许重复,比如std ::组。不要从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,所以这是一个很好的方法 - 但是有一些关于制作你自己的包装类的好东西和完整的东西。您可以直接了解操作的复杂性,并且可能不需要完全反向映射值=&gt;由Boost双向映射提供的密钥。
答案 6 :(得分:1)
您要求的正是std::find所做的(不是成员函数)
template< class InputIt, class T >
InputIt find( InputIt first, InputIt last, const T& value );
答案 7 :(得分:0)
不是一个非常好的选项,但在用户在初始化时分配默认值(如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;
}
答案 8 :(得分:0)
如果有人来这里寻找c ++ 11及更高版本,我正在添加此答案。
//DECLARE A MAP
std::map<int, int> testmap;
//SAMPLE DATA
testmap.insert(std::make_pair(1, 10));
testmap.insert(std::make_pair(2, 20));
testmap.insert(std::make_pair(3, 30));
testmap.insert(std::make_pair(4, 20));
//ELEMENTS WITH VALUE TO BE FOUND
int value = 20;
//RESULTS
std::map<int, int> valuesMatching;
//ONE STEP TO FIND ALL MATCHING MAP ELEMENTS
std::copy_if(testmap.begin(), testmap.end(), std::inserter(valuesMatching, valuesMatching.end()), [value](const auto& v) {return v.second == value; });
答案 9 :(得分:-3)
可能我不完全明白你想要完成的事情。但是,为了简单地测试地图是否包含值,我相信您可以使用内置std::map
的{{1}}。
find