web-dev-qa-db-ja.com

std :: mapに値が存在することを確認する-C ++

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

編集

値、キーの組み合わせを保存する別のマップを内部で使用してはどうですか。だから私はそれを見つけることができますか? std :: mapのfind()は順次検索を実行していますか?

ありがとう

30
Navaneeth K N

boost :: multi_index を使用して bidirectional map を作成できます-ペアのいずれかの値をキーとして使用して、クイックルックアップを実行できます。

20
Mark Ransom

優れた boost ライブラリにアクセスできる場合は、 boost :: multi_index を使用して bidirectional map を作成する必要があります。 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;
    }
}
16
CodeBuddy

値、キーの組み合わせを保存する別のマップを内部で使用してはどうですか。だから私はそれを見つけることができますか?

はい:2つのマップを維持します。1つのマップは1つのタイプのキーを使用し、もう1つのマップはもう1つのタイプを使用します。

Std :: mapのfind()は順次検索を実行していますか?

いいえ、ソートされたツリーのバイナリ検索です。速度はO(log(n))です。

15
ChrisW

Boostの双方向マップを調べます。 http://www.boost.org/doc/libs/1_38_0/libs/bimap/doc/html/index.html

これにより、両方の値がキーのように機能します。

それ以外の場合、反復が進むべき道です。

6
Evan Teran

この機能を試してください:

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

便利だと思う

4
Mitch

いいえ、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双方向マップによって提供される値=>キーの完全な逆マッピングは必要ない場合があります。

2
James Thompson

あなたが要求しているのはまさに std :: find が行うことです(メンバー関数ではありません)

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

誰かがここに来て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; });
0
Pavan Chandaka

最適なオプションではありませんが、初期化時にユーザーが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;
}
0
user2761565