Comment vérifier si std :: map contient une clé sans faire d'insertion?

148

Le seul moyen que j'ai trouvé pour vérifier les doublons est d'insérer et de vérifier le std::pair.secondfor false, mais le problème est que cela insère toujours quelque chose si la clé n'est pas utilisée, alors que ce que je veux, c'est une map.contains(key);fonction.

jmasterx
la source

Réponses:

305

Utiliser my_map.count( key ); il ne peut renvoyer que 0 ou 1, ce qui est essentiellement le résultat booléen souhaité.

Fonctionne my_map.find( key ) != my_map.end()aussi alternativement .

Potatoswatter
la source
40
@John: Ça sent l'optimisation prématurée. Sur GCC (et je suis sûr que la plupart des systèmes raisonnables), map::countest implémenté comme find(__x) == end() ? 0 : 1;. Pour multimaple vous pouvez avoir un argument de performance, mais ce n'est pas la question d'OP et je préfère toujours l'élégance.
Potatoswatter
42
Non, l'argument d'optimisation prématurée n'est valable que si l'optimisation demande un certain effort, ce qui n'est pas le cas dans ce cas.
markh44
13
Pas vrai. Ce n'est pas prématuré si cela facilite la lecture du code ou élimine la surcharge inutile. Dans ce cas, si count () est implémenté via find () de toute façon, alors l'appel de find () élimine directement un appel de fonction ... ergo, c'est une optimisation mature . Je trouve que l'utilisation de l'appel find () est également plus évidente, mais c'est une préférence purement personnelle.
Tim Keating le
9
Ce n'est pas une optimisation prématurée d'être conscient de la performance des fonctions de la bibliothèque avant de prendre l'habitude de les utiliser. Dans ce cas, vous avez raison, cela n'a pas d'importance, mais la minuscule différence stylistique entre trouver et compter. Je pense que vous allez trop loin dans la rhétorique de «l'optimisation prématurée». Vous devriez prendre toutes les habitudes d'optimisation «gratuites» que vous pouvez trouver et les utiliser pour le développement quotidien. C'est lorsque les codeurs succombent au piège de payer les coûts en lisibilité / temps de développement / etc, le tout pour des «gains de performance» non mesurés que la rhétorique de l'optimisation prématurée devient le bon conseil à donner.
VoidStar
10
Loin de là, std devrait simplement ajouter un putain has(k)/ contains(k)comme toute autre classe de carte sensée de la planète. Mauvaise conception de l'interface. L'approche find () est trop verbeuse et l' count(k)approche n'est certainement pas à la parité sémantique avec has(k). Pour cette question non plus find(k). Vérifiez le nombre de vues sur cette question.
Jarrod Smith
46

La réponse de Potatoswatter est correcte, mais je préfère utiliser findou à la lower_boundplace. lower_boundest particulièrement utile car l'itérateur renvoyé peut ensuite être utilisé pour une insertion suggérée, si vous souhaitez insérer quelque chose avec la même clé.

map<K, V>::iterator iter(my_map.lower_bound(key));
if (iter == my_map.end() || key < iter->first) {    // not found
    // ...
    my_map.insert(iter, make_pair(key, value));     // hinted insertion
} else {
    // ... use iter->second here
}
Chris Jester-Young
la source
C'est subtilement différent de la façon dont il dit qu'il le fait… la seule différence est que le calcul de valuepeut être ignoré si l'insertion n'est pas nécessaire.
Potatoswatter
1
Bien sûr, je comprends que l'OP ne se soucie pas d'insérer, donc une lower_boundsolution basée sur une solution est exagérée. Je viens de mentionner ma réponse "par souci d'exhaustivité"; comme je l'ai dit, la vôtre est parfaitement adéquate. :-)
Chris Jester-Young
4
Oui, c'est une bonne réponse et je ne suis pas en désaccord avec quoi que ce soit. Soulignant simplement le rapport à l'alternative de l' inserta priori. En fait, il y a une autre différence si vous utilisez a multimap, la lower_boundméthode insère au début de la plage équivalente alors que la insertméthode simple ajoute à la fin de la plage.
Potatoswatter
2
Pas la réponse à la question, mais ma pauvre question qui me pose me conduit à la bonne réponse ici ... Je dois faire l'insertion / la mise à jour. : D
Hunter-Orionnoir
1
@Hunter Pouvez-vous me montrer votre code? Si ce n'est pas énorme, je peux probablement l'examiner pour vous.
Chris Jester-Young
9

Votre desideratum,, map.contains(key)est prévu pour le projet de norme C ++ 2a . En 2017, il a été implémenté par gcc 9.2 . C'est aussi dans le bruit actuel .

Camille Goudeseune
la source
C'est une fonctionnalité intéressante! Je pense qu'il a atterri sur C ++ 20. cppreference.com
Franklin Yu