J'ai une carte 1 à 1. Quelle est la meilleure façon de trouver des clés à partir de valeurs,
c'est à dire.
Par exemple, si la carte est la suivante
VALEUR CLÉ
a 1
b 2
c 3
d 4
Je veux pouvoir trouver que la clé correspondant à 3 est C.
Merci!
Vous ne pouvez pas faire grand-chose à ce sujet. Vous avez des options pour travailler avec deux cartes, utiliser une carte à touches multiples comme celle de la bibliothèque Boost Multi-Index , ou faire une recherche linéaire.
MISE À JOUR: La solution la plus légère prête à l'emploi semble être Boost.Bimap , qui signifie carte bidirectionnelle.
Disons que vous avez une carte<X,Y>
. Construisez une deuxième structure, peut-être une map<Y*,X*,Deref>
qui permet la recherche inversée mais évite de doubler la surcharge de stockage, car, à l'aide de pointeurs, il n'est pas nécessaire de stocker chaque X et Y deux fois. La deuxième structure a simplement des pointeurs dans la première.
Le moyen le plus direct serait de maintenir une carte parallèle où les valeurs et les clés sont inversées (puisque la relation est une à une).
Une autre solution serait d'utiliser (la moins connue?) Boost.Bimap :
Boost.Bimap est une bibliothèque de cartes bidirectionnelles pour C++. Avec Boost.Bimap, vous pouvez créer des conteneurs associatifs dans lesquels les deux types peuvent être utilisés comme clé. UNE
bimap<X,Y>
peut être considéré comme une combinaison d'unstd::map<X,Y>
et unstd::map<Y,X>
. La courbe d'apprentissage du bimap est presque plate si vous savez utiliser des conteneurs standard. Beaucoup d'efforts ont été déployés pour cartographier le schéma de dénomination de la STL dans Boost.Bimap. La bibliothèque est conçue pour correspondre aux conteneurs STL courants.
À moins que la carte soit immense ou que vous ayez une autre façon de savoir que la recherche linéaire est trop lente, je commencerais par la recherche linéaire:
#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";
}
Une variante de la réponse de @ Robᵩ ci-dessus qui utilise un lambda:
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";
}
(merci à @Nawaz pour sa contribution ici: https://stackoverflow.com/a/19828596/1650814 )
Je sais que c'est une très vieille question, mais cet article de codeproject ( http://www.codeproject.com/Articles/3016/An-STL-like-bidirectional-map ) est un assez bon exemple de une carte bidirectionnelle.
Voici un exemple de programme qui montre à quel point c'est simple:
#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;
}
Donné un std::map
des clés aux valeurs, la fonction suivante renverra une table de recherche inversée, un std::map
des valeurs aux clés.
/// 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;
}