Quel est le meilleur moyen de déterminer si une carte STL contient une valeur pour une clé donnée?
#include <map>
using namespace std;
struct Bar
{
int i;
};
int main()
{
map<int, Bar> m;
Bar b = {0};
Bar b1 = {1};
m[0] = b;
m[1] = b1;
//Bar b2 = m[2];
map<int, Bar>::iterator iter = m.find(2);
Bar b3 = iter->second;
}
En examinant cela dans un débogueur, il semble que iter
ne soit que des données vides.
Si je ne commente pas cette ligne:
Bar b2 = m[2]
Le débogueur indique que b2
est {i = 0}
. (Je suppose que cela signifie que l'utilisation d'un index non défini retournera une structure avec toutes les valeurs vides/non initialisées?)
Aucune de ces méthodes n'est si géniale. Ce que j'aimerais vraiment, c'est une interface comme celle-ci:
bool getValue(int key, Bar& out)
{
if (map contains value for key)
{
out = map[key];
return true;
}
return false;
}
Existe-t-il quelque chose dans ce sens?
Existe-t-il quelque chose dans ce sens?
Non. Avec la classe de carte stl, vous utilisez ::find()
pour rechercher dans la carte et comparez l'itérateur renvoyé à std::map::end()
.
alors
map<int,Bar>::iterator it = m.find('2');
Bar b3;
if(it != m.end())
{
//element found;
b3 = it->second;
}
Vous pouvez évidemment écrire votre propre routine getValue()
si vous le souhaitez (également en C++, il n’ya aucune raison d’utiliser out
), mais je soupçonne qu’une fois que vous aurez appris à utiliser std::map::find()
, vous ne voudrez plus gaspiller votre temps.
Votre code est également légèrement faux:
m.find('2');
recherchera sur la carte une valeur de clé égale à '2'
. Le compilateur C++ IIRC convertira implicitement "2" en un entier, ce qui donne la valeur numérique pour le code ASCII pour "2", ce qui n'est pas ce que vous voulez.
Étant donné que votre type de clé dans cet exemple est int
, vous souhaitez effectuer une recherche comme suit: m.find(2);
Tant que la carte n’est pas une carte multiple, l’un des moyens les plus élégants serait d’utiliser la méthode de comptage.
if (m.count(key))
// key exists
Le compte serait 1 si l'élément est effectivement présent dans la carte.
Il existe déjà avec find, mais pas dans cette syntaxe exacte.
if (m.find(2) == m.end() )
{
// key 2 doesn't exist
}
Si vous voulez accéder à la valeur si elle existe, vous pouvez faire:
map<int, Bar>::iterator iter = m.find(2);
if (iter != m.end() )
{
// key 2 exists, do something with iter->second (the value)
}
Avec C++ 0x et auto, la syntaxe est plus simple:
auto iter = m.find(2);
if (iter != m.end() )
{
// key 2 exists, do something with iter->second (the value)
}
Je vous recommande de vous y habituer plutôt que d'essayer de trouver un nouveau mécanisme pour le simplifier. Vous pourrez peut-être réduire un peu le code, mais considérez le coût de le faire. Vous avez maintenant introduit une nouvelle fonction que les personnes familiarisées avec C++ ne pourront pas reconnaître.
Si vous voulez quand même implémenter cela malgré ces avertissements, alors:
template <class Key, class Value, class Comparator, class Alloc>
bool getValue(const std::map<Key, Value, Comparator, Alloc>& my_map, int key, Value& out)
{
typename std::map<Key, Value, Comparator, Alloc>::const_iterator it = my_map.find(key);
if (it != my_map.end() )
{
out = it->second;
return true;
}
return false;
}
Je viens de remarquer qu'avec C++ 2 , nous aurons
std::map::contains( const Key& key ) const;
Cela retournera true si map contient un élément avec la clé key
.
amap.find
renvoie amap::end
s'il ne trouve pas ce que vous cherchez - vous êtes censé vérifier cela.
Vérifiez la valeur de retour de find
par rapport à end
.
map<int, Bar>::iterator it = m.find('2');
if ( m.end() != it ) {
// contains
...
}
Pour résumer succinctement certaines des autres réponses:
Si vous n'utilisez pas encore C++ 20, vous pouvez écrire votre propre fonction mapContainsKey
:
bool mapContainsKey(std::map<int, int>& map, int key)
{
if (map.find(key) == map.end()) return false;
return true;
}
Si vous souhaitez éviter de nombreuses surcharges pour map
vs unordered_map
et pour différents types de clé et de valeur, vous pouvez en faire une fonction template
.
Si vous utilisez C++ 20
ou une version ultérieure, il y aura une fonction intégrée contains
:
std::map<int, int> myMap;
// do stuff with myMap here
int key = 123;
if (myMap.contains(key))
{
// stuff here
}
Vous pouvez créer votre fonction getValue avec le code suivant:
bool getValue(const std::map<int, Bar>& input, int key, Bar& out)
{
std::map<int, Bar>::iterator foundIter = input.find(key);
if (foundIter != input.end())
{
out = foundIter->second;
return true;
}
return false;
}
Si vous voulez déterminer si une clé est présente ou non dans la carte, vous pouvez utiliser la fonction membre find () ou count () de la carte. La fonction find qui est utilisée ici dans l'exemple renvoie l'itérateur à element ou map :: end sinon. En cas de décompte, le décompte retourne 1 s'il est trouvé, sinon il renvoie zéro (ou sinon).
if(phone.count(key))
{ //key found
}
else
{//key not found
}
for(int i=0;i<v.size();i++){
phoneMap::iterator itr=phone.find(v[i]);//I have used a vector in this example to check through map you cal receive a value using at() e.g: map.at(key);
if(itr!=phone.end())
cout<<v[i]<<"="<<itr->second<<endl;
else
cout<<"Not found"<<endl;
}