c++ - Comment trouver si une clé donnée existe dans un C ++ std :: map


J'essaie de vérifier si une clé donnée est dans une carte et ne peut pas le faire:

typedef map<string,string>::iterator mi;
map<string, string> m;
m.insert(make_pair("f","++--"));
pair<mi,mi> p = m.equal_range("f");//I'm not sure if equal_range does what I want
cout << p.first;//I'm getting error here

alors comment puis-je imprimer ce qui est en p?


Answers



Utilisez map::find

if ( m.find("f") == m.end() ) {
  // not found
} else {
  // found
}



Pour vérifier si une clé particulière existe dans la map, utilisez la fonction de membre count de l'une des manières suivantes:

m.count(key) > 0
m.count(key) == 1
m.count(key) != 0

La documentation de map::find dit: "Une autre fonction membre, map::count , peut être utilisée pour vérifier si une clé particulière existe."

La documentation pour map::count dit: "Parce que tous les éléments dans un conteneur de carte sont uniques, la fonction ne peut retourner que 1 (si l'élément est trouvé) ou zéro (sinon)."

Pour récupérer une valeur de la carte via une clé dont vous savez qu'elle existe, utilisez map :: at :

value = m.at(key)

Contrairement à map :: operator [] , map::at ne créera pas une nouvelle clé dans la map si la clé spécifiée n'existe pas.




Vous pouvez utiliser .find() :

map<string,string>::iterator i = m.find("f");

if (i == m.end()) { /* Not found */ }
else { /* Found, i->first is f, i->second is ++-- */ }



m.find == m.end() // not found 

Si vous souhaitez utiliser une autre API, recherchez go pour m.count(c)>0

 if (m.count("f")>0)
      cout << " is an element of m.\n";
    else 
      cout << " is not an element of m.\n";



Je pense que tu veux map::find . Si m.find("f") est égal à m.end() , la clé n'a pas été trouvée. Sinon, find renvoie un itérateur pointant sur l'élément trouvé.

L'erreur est que p.first est un itérateur, qui ne fonctionne pas pour l'insertion de flux. Changez votre dernière ligne à cout << (p.first)->first; . p est une paire d'itérateurs, p.first est un itérateur, p.first->first est la chaîne de clé.

Une map ne peut avoir qu'un seul élément pour une clé donnée, donc equal_range n'est pas très utile. Il est défini pour map, car il est défini pour tous les conteneurs associatifs, mais il est beaucoup plus intéressant pour multimap.




Soyez prudent en comparant le résultat de la recherche avec la fin comme pour la carte 'm' comme toutes les réponses ont fait au-dessus de la carte :: iterator i = m.find ("f");

 if (i == m.end())
 {
 }
 else
 {
 }  

vous ne devriez pas essayer d'effectuer une opération telle que l'impression de la clé ou de la valeur avec l'itérateur i si son égal à m.end () sinon cela conduira à une erreur de segmentation.




map<string, string> m;

check key existe ou non, et retourne le nombre de occurences (0/1 sur la carte):

int num = m.count("f");  
if (num>0) {    
    //found   
} else {  
    // not found  
}

check key existe ou non, et retourne l'itérateur:

map<string,string>::iterator mi = m.find("f");  
if(mi != m.end()) {  
    //found  
    //do something to mi.  
} else {  
    // not found  
}  

dans votre question, l'erreur causée par la mauvaise surcharge de l' operator<< car p.first est map<string, string> , vous ne pouvez pas l'imprimer. essaye ça:

if(p.first != p.second) {
    cout << p.first->first << " " << p.first->second << endl;
}



template <typename T, typename Key>
bool key_exists(const T& container, const Key& key)
{
    return (container.find(key) != std::end(container));
}

Bien sûr, si vous vouliez obtenir un colombophile, vous pourriez toujours créer une fonction qui prendrait aussi une fonction trouvée et une fonction non trouvée, quelque chose comme ceci:

template <typename T, typename Key, typename FoundFunction, typename NotFoundFunction>
void find_and_execute(const T& container, const Key& key, FoundFunction found_function, NotFoundFunction not_found_function)
{
    auto& it = container.find(key);
    if (it != std::end(container))
    {
        found_function(key, it->second);
    }
    else
    {
        not_found_function(key);
    }
}

Et utilisez-le comme ceci:

    std::map<int, int> some_map;
    find_and_execute(some_map, 1,
        [](int key, int value){ std::cout << "key " << key << " found, value: " << value << std::endl; },
        [](int key){ std::cout << "key " << key << " not found" << std::endl; });

L'inconvénient est de trouver un bon nom, "find_and_execute" est maladroit et je ne peux rien trouver de mieux sur le dessus de ma tête ...




En comparant le code de std :: map :: find et std :: map :: count, je dirais que le premier peut donner un avantage de performance:

const_iterator find(const key_type& _Keyval) const
    {   // find an element in nonmutable sequence that matches _Keyval
    const_iterator _Where = lower_bound(_Keyval); // Here one looks only for lower bound
    return (_Where == end()
        || _DEBUG_LT_PRED(this->_Getcomp(),
            _Keyval, this->_Key(_Where._Mynode()))
                ? end() : _Where);
    }

size_type count(const key_type& _Keyval) const
    {   // count all elements that match _Keyval
    _Paircc _Ans = equal_range(_Keyval); // Here both lower and upper bounds are to be found, which is presumably slower.
    size_type _Num = 0;
    _Distance(_Ans.first, _Ans.second, _Num);
    return (_Num);
    }



Si vous voulez comparer une paire de cartes, vous pouvez utiliser cette méthode:

typedef map<double, double> TestMap;
TestMap testMap;
pair<map<double,double>::iterator,bool> controlMapValues;

controlMapValues= testMap.insert(std::pair<double,double>(x,y));
if (controlMapValues.second == false )
{
    TestMap::iterator it;
    it = testMap.find(x);

    if (it->second == y)
    {
        cout<<"Given value is already exist in Map"<<endl;
    }
}

C'est une technique utile.