2009-02-11 89 views
26

我知道找到方法找到提供的键std :: map并返回一个迭代器到元素。无论如何找到这个值并获得元素的迭代器吗?我需要做的是检查std :: map中存在的指定值。我通过循环地图中的所有项目并进行比较来完成此操作。但我想知道是否有更好的方法。检查std :: map中存在的值 - C++

这是我写的有

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; 
} 

编辑

如何内部使用另一个地图存储值,组合键。所以我可以打电话找它?是在std :: map中查找()做顺序搜索?

谢谢

回答

19

您可以使用boost::multi_index创建一个bidirectional map - 您可以使用该对的任一值作为快速查找的关键。

+0

你打败了我:)好的答案。 – 2009-02-11 03:47:40

2

不,你必须遍历std :: map并手动检查所有值。根据你想要做什么,你可以将std :: map包装在一个简单的类中,该类也可以将所有插入到地图中的值缓存在容易搜索的东西中,并且不允许重复,比如std ::组。不要从性病::地图继承(它没有虚析构函数!),但把它包起来,这样就可以做这样的事情:

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双向映射提供的值=>键的完全反向映射。

+0

他想要一个元素的迭代器,所以你想要使用第二个map <>而不是set <>。 – 2009-02-11 04:01:50

14

如何使用内部存储值,组合键的内部另一个映射。所以我可以打电话找它?

是:维护两张地图,一张地图使用一种类型的键,另一种使用另一种。

find()在std :: map中进行顺序搜索吗​​?

不,这是一个排序树的二进制搜索:它的速度是O(log(n))。

+0

这很有道理。因此,维护两张地图会比顺序搜索和查找价值更好,对吗? – 2009-02-11 03:57:59

+3

插入或删除任何东西需要两倍的时间(使用两张地图代替一张);但是对于大量元素来说,查找会快很多,因为O(log(n))远小于顺序搜索所需的O(n)。 – ChrisW 2009-02-11 04:03:20

+0

伟大的克里斯。谢谢。 – 2009-02-11 04:05:38

15

如果您有权访问优秀的boost库,那么您应该使用boost::multi_index来创建bidirectional map,正如Mark所说的那样。与std :: map不同,这允许您通过键或值来查找。

如果你只有STL手下面的代码就可以了(模板与任何类型的地图,其中mapped_type支持==操作符的工作):

#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; 
    } 
} 
-3

可能,我不充分理解你想要完成的事情。但为了简单测试一张地图是否包含一个值,我相信你可以使用内建于find内的std::map

bool ContainsValue(Type_ value) 
{ 
    return (internalMap.find(value) != internalMap.end()); 
} 
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; 
} 

我觉得

0

你所请求的正是std::find呢(而不是成员函数)

template< class InputIt, class T > 
InputIt find(InputIt first, InputIt last, const T& value); 
0

不是非常有用非常好的选择,但在少数情况下用户在初始化时分配默认值(如0或NULL)时可能会有用ialization。

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; 
}