31

我知道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 中的find()是否进行顺序搜索?

谢谢

4

10 回答 10

20

您可以使用boost::multi_index创建双向映射- 您可以使用该对的任一值作为键来进行快速查找。

于 2009-02-11T03:46:00.257 回答
17

如果您可以访问出色的boost库,那么您应该使用boost::multi_index来创建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;
    }
}
于 2009-05-24T21:52:52.687 回答
15

如何在内部使用另一个存储值、键组合的地图。所以我可以调用 find 吗?

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

std::map 中的 find() 是否进行顺序搜索?

不,这是对排序树的二分搜索:它的速度是 O(log(n))。

于 2009-02-11T03:53:55.930 回答
6

查看 boost 的双向映射: http: //www.boost.org/doc/libs/1_38_0/libs/bimap/doc/html/index.html

它让两个值都像一个键一样起作用。

否则,迭代是要走的路。

于 2009-02-11T03:46:55.200 回答
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;
}

我认为它很有用

于 2011-07-13T19:21:39.987 回答
4

您所要求的正是std::find所做的(不是成员函数)

template< class InputIt, class T >
InputIt find( InputIt first, InputIt last, const T& value );
于 2017-03-08T13:15:19.477 回答
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,所以这是一个很好的方法 - 但是制作你自己的包装类有一些很好和完整的东西。您的优势在于可以直接了解操作的复杂性,并且您可能不需要 Boost 双向映射提供的值 => 键的完整反向映射。

于 2009-02-11T03:40:47.413 回答
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;
}
于 2017-04-06T09:39:56.937 回答
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; });
于 2018-11-16T00:54:01.473 回答
-3

可能我不完全理解您要完成的工作。但是为了简单地测试一个地图是否包含一个值,我相信你可以使用std::map内置的find.

bool ContainsValue(Type_ value)
{
    return (internalMap.find(value) != internalMap.end());
}
于 2010-12-01T19:16:55.317 回答