web-dev-qa-db-fra.com

Comment trouver si une clé donnée existe dans un st ++ :: map C ++

J'essaie de vérifier si une clé 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 dans p?

397

Utilisez map::find

_if ( m.find("f") == m.end() ) {
  // not found
} else {
  // found
}
_
624
anon

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

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

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

La documentation pour map::count indique: "Comme tous les éléments d'un conteneur de carte sont uniques, la fonction ne peut renvoyer 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 de nouvelle clé dans la carte si la clé spécifiée n'existe pas.

282
DavidRR

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 ++-- */ }
34
Thomas Bonini
m.find == m.end() // not found 

Si vous voulez utiliser une autre API, trouvez alors allez 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";
14
aJ.

C++ 2 nous donne std::map::contains pour le faire.

#include <iostream>
#include <string>
#include <map>

int main()
{
    std::map<int, std::string> example = {{1, "One"}, {2, "Two"}, 
                                     {3, "Three"}, {42, "Don\'t Panic!!!"}};

    if(example.contains(42)) {
        std::cout << "Found\n";
    } else {
        std::cout << "Not found\n";
    }
}
12
Denis Sablukov

Je pense que vous voulez map::find. Si m.find("f") est égal à m.end(), la clé est introuvable. Sinon, find renvoie un itérateur pointant sur l'élément trouvé.

L'erreur est due au fait que p.first est un itérateur qui ne fonctionne pas pour l'insertion de flux. Changez votre dernière ligne en 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 carte ne peut avoir qu'un seul élément pour une clé donnée, donc equal_range n'est pas très utile. C'est défini pour map, car il est défini pour tous les conteneurs associatifs, mais c'est beaucoup plus intéressant pour multimap.

12
Steve Jessop
map<string, string> m;

clé de contrôle existe ou non, et retourne le nombre d'occurrences (0/1 dans la carte):

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

clé de contrôle existe ou pas, et retourne 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 provoquée par une surcharge operator<< mauvaise, parce que 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;
}
4
hustljian
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 voulez devenir plus chic, vous pouvez toujours créer une fonction qui prend 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 de cette idée est de trouver un bon nom, "find_and_execute" est maladroit et je ne peux rien trouver de mieux à mon esprit ...

4
Lambage

Faites attention en comparant le résultat de la recherche avec la fin, comme pour la carte 'm', comme toutes les réponses l'ont fait ci-dessus, map :: iterator i = m.find ("f");

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

vous ne devez pas essayer d’effectuer une opération telle que l’impression de la clé ou de la valeur avec l’itérateur i si sa valeur est égale à m.end (), sinon cela entraînerait une erreur de segmentation.

3
Invictus

C++17 l'a simplifié un peu plus avec un If statement with initializer. De cette façon, vous pouvez avoir votre gâteau et le manger aussi.

if ( auto it{ m.find( "key" ) }; it != std::end( m ) ) 
{
    // Destructure the returned pair in to 
    // its sub components. Get them by reference.
    // You can also get them by value.
    auto&[ key, value ] { *it };

    // Grab either the key or value stored in the pair.
    // The key is stored in the 'first' variable and
    // the 'value' is stored in the second.
    auto& mkey{ it->first };
    auto& mvalue{ it->second };

    // That or just grab the entire pair pointed
    // to by the iterator.
    auto& pair{ *it };
} 
else 
{
   // Key was not found..
}
3
WBuck

En comparant le code de std :: map :: find et de std :: map :: count, je dirais que le premier peut générer un avantage en termes de performances:

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);
    }
0
Hope