web-dev-qa-db-ja.com

逆マップ検索

1対1のマップがあります。値からキーを見つける最良の方法は何ですか、

つまり.

マップがこれである場合の例

キーバリュー

a    1
b    2
c    3 
d    4

3に対応するキーがCであることを見つけたい.

ありがとう!

40
user620189

それについてできることはあまりありません。 2つのマップを操作するオプション、 Boost Multi-Index libraryのようなマルチキーマップを使用するオプション、または線形検索を実行するオプションがあります。

UPDATE:箱から出したソリューションの中で最も軽量なのは Boost.Bimap で、双方向マップの略です。

30
user405725

Map<X,Y>があるとします。 2番目の構造、おそらく逆ルックアップを有効にしますが、ストレージオーバーヘッドの倍増を回避するmap<Y*,X*,Deref>を構築します。ポインターを使用すると、各XとYを2回保存する必要がないためです。 2番目の構造体には、最初の構造体へのポインターがあります。

11
Amit

最も直接的な方法は、値とキーが逆になる並列マップを維持することです(関係は1対1であるため)。

8
MAK

別の解決策は、(あまり知られていない?) Boost.Bimap を使用することです。

Boost.Bimapは、C++用の双方向マップライブラリです。 Boost.Bimapを使用すると、両方のタイプをキーとして使用できる連想コンテナを作成できます。 bimap<X,Y>は、std::map<X,Y>std::map<Y,X>の組み合わせと考えることができます。標準コンテナの使用方法を知っている場合、bimapの学習曲線はほぼ平坦です。 Boost.BimapでのSTLの命名スキームのマッピングに多大な努力が注がれました。ライブラリは、一般的なSTLコンテナに一致するように設計されています。

マップが巨大であるか、線形検索が遅すぎることを知る他の方法がない限り、線形検索から始めます。

#include <iostream>
using std::cout;

#include <map>
using std::map;

#include <algorithm>
using std::find_if;

#include <boost/assign/list_of.hpp>
using boost::assign::map_list_of;

typedef map<char, int> Map;
typedef Map::key_type Key;
typedef Map::value_type Pair;
typedef Map::mapped_type Value;


struct Finder {
    const Value v;
    Finder(const Value& v) : v(v) {}
    bool operator()(const Pair& p) {
        return p.second == v;
    }
};

Map m = map_list_of('a', 1)('b', 2)('c', 3)('d', 4)('e', 5);

int main() {
    Pair v = *find_if(m.begin(), m.end(), Finder(3));
    cout << v.second << "->" << v.first << "\n";
}
4
Robᵩ

ラムダを使用する上記の@Rob variationの回答のバリエーション:

map<char, int> m = {{'a', 1}, {'b', 2}, {'c', 3}, {'d', 4}, {'e', 5}};

int findVal = 3;
auto it = find_if(m.begin(), m.end(), [findVal](const Pair & p) {
    return p.second == findVal;
});
if (it == m.end()) {
    /*value not found*/
    cout << "*value not found*";
}
else {
    Pair v = *it;
    cout << v.second << "->" << v.first << "\n";
}

(ここに貢献してくれた@Nawazに感謝します: https://stackoverflow.com/a/19828596/1650814

3
WXB13

これは本当に古い質問ですが、このコードプロジェクトの記事( http://www.codeproject.com/Articles/3016/An-STL-like-bidirectional-map )はかなり良い例です双方向マップ。

これは、それがいかに簡単かを示すサンプルプログラムです。

 #pragma warning(disable:4503)

    #include "bimap.h"
    #include <iostream>
    #include <string>

    using codeproject::bimap;

    int main(void)
    {
      bimap<int,std::string> bm;

      bm[1]="Monday";
      bm[2]="Tuesday";
      bm[3]="Wednesday";
      bm[4]="Thursday";
      bm[5]="Friday";
      bm[6]="Saturday";
      bm[7]="Sunday";

      std::cout<<"Thursday occupies place #"<<bm["Thursday"]<<
                 " in the week (european style)"<<std::endl;
      return 0;
    }
2
Yannick Lange

std::mapキーから値まで、次の関数は逆ルックアップテーブル、std::map値からキーへ。

    /// Given a map from keys to values, creates a new map from values to keys 
    template<typename K, typename V>
    static map<V, K> reverse_map(const map<K, V>& m) {
        map<V, K> r;
        for (const auto& kv : m)
            r[kv.second] = kv.first;
        return r;
    }
1
cdiggins