代码之家  ›  专栏  ›  技术社区  ›  Navaneeth K N

在STD中存在检查值::MAP- C++

  •  30
  • Navaneeth K N  · 技术社区  · 16 年前

    我知道 找到 方法在中查找提供的键 STD::地图 并向元素返回迭代器。是否仍要查找值并获取元素的迭代器?我需要做的是检查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;
    }
    

    编辑

    在内部使用另一个存储值和键组合的映射如何?所以我可以打电话找它?是 查找() 在std::map中进行顺序搜索?

    谢谢

    10 回复  |  直到 16 年前
        1
  •  20
  •   Mark Ransom    16 年前

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

        2
  •  16
  •   CodeBuddy    16 年前

    如果你能接触到优秀的 boost 图书馆,那么你应该用 boost::multi_index 创造 bidirectional map 正如马克所说。与std::map不同,这允许您通过键或值进行查找。

    如果您只有STL可供使用,那么下面的代码就可以实现这一点(模板化以使用映射类型支持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;
        }
    }
    
        3
  •  15
  •   ChrisW    16 年前

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

    是:维护两个映射,一个使用一种键,另一个使用另一种键。

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

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

        4
  •  6
  •   Evan Teran    16 年前

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

    它让两个值都像一个键。

    否则,迭代就是前进的道路。

        5
  •  4
  •   Mitch    13 年前

    尝试此功能:

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

    我觉得这很有用

        6
  •  2
  •   James Thompson    16 年前

    不,您必须循环遍历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,滚动你自己的小包装类有多困难。我喜欢Boost,所以这是一个很好的方法-但是有一个很好和完整的方法来创建自己的包装类。您可以直接理解操作的复杂性,并且可能不需要Boost双向映射提供的值的完全反向映射=>键。

        7
  •  1
  •   Vaidas    8 年前

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

    template< class InputIt, class T >
    InputIt find( InputIt first, InputIt last, const T& value );
    
        8
  •  0
  •   Shail Gautam    8 年前

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

    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;
    }
    
        9
  •  0
  •   Pavan Chandaka    6 年前

    我添加这个答案,如果有人来到这里,寻找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; });
    
        10
  •  -3
  •   Ternary    14 年前

    可能我不完全理解你想完成什么。但是为了简单地测试一个映射是否包含一个值,我相信您可以使用 std::map 建在 find .

    bool ContainsValue(Type_ value)
    {
        return (internalMap.find(value) != internalMap.end());
    }