Wie kann ich überprüfen, ob std :: map einen Schlüssel enthält, ohne ihn einzufügen?

147

Der einzige Weg , die ich gefunden habe nach Duplikaten überprüfen ist , durch Einfügen und Prüfen des std::pair.secondfür false, aber das Problem ist , dass dies etwas noch einfügt , wenn der Schlüssel nicht verwendet wird, während das, was ich will ist eine map.contains(key);Funktion.

jmasterx
quelle

Antworten:

304

Verwenden Sie my_map.count( key ); Es kann nur 0 oder 1 zurückgeben, was im Wesentlichen das gewünschte boolesche Ergebnis ist.

Funktioniert auch alternativ my_map.find( key ) != my_map.end().

Kartoffelklatsche
quelle
40
@ John: Das stinkt nach vorzeitiger Optimierung. Auf GCC (und ich bin sicher die vernünftigsten Systeme) map::countwird als implementiert find(__x) == end() ? 0 : 1;. Für multimapdie haben Sie vielleicht ein Leistungsargument, aber das ist nicht die Frage von OP und ich bevorzuge immer noch Eleganz.
Potatoswatter
42
Nein, das Argument der vorzeitigen Optimierung ist nur gültig, wenn die Optimierung einige Anstrengungen erfordert, in diesem Fall jedoch nicht.
Markh44
13
Nicht wahr. Es ist nicht verfrüht, wenn es den Code leichter lesbar macht oder unnötigen Overhead eliminiert. In diesem Fall, wenn count () ohnehin über find () implementiert ist, eliminiert der Aufruf von find () direkt einen Funktionsaufruf ... ergo, es ist eine ausgereifte Optimierung. Ich finde, dass die Verwendung des Aufrufs find () ebenfalls offensichtlicher ist, aber das ist eine rein persönliche Präferenz.
Tim Keating
9
Es ist keine vorzeitige Optimierung, sich der Leistung von Bibliotheksfunktionen bewusst zu sein, bevor Sie sich angewöhnen, diese zu verwenden. In diesem Fall haben Sie Recht, es spielt keine Rolle, aber auch nicht der winzige stilistische Unterschied zwischen Finden und Zählen. Ich denke, Sie gehen zu weit von der Rhetorik der vorzeitigen Optimierung. Sie sollten alle "freien" Optimierungsgewohnheiten, die Sie finden können, für die tägliche Entwicklung verwenden. Wenn Codierer der Falle erliegen, Kosten in Bezug auf Lesbarkeit / Entwicklungszeit / usw. zu zahlen, alles für nicht gemessene "Leistungssteigerungen", wird die vorzeitige Optimierungsrhetorik zum richtigen Ratschlag.
VoidStar
10
Weit draußen sollte std einfach eine verdammt has(k)/ contains(k)wie jede andere vernünftige Kartenklasse auf dem Planeten hinzufügen . Schlechtes Interface-Design. Der find () -Ansatz ist zu ausführlich und der count(k)Ansatz steht definitiv nicht in semantischer Parität mit has(k). Im Übrigen ist es auch nicht find(k). Überprüfen Sie die Anzahl der Aufrufe zu dieser Frage.
Jarrod Smith
46

Die Antwort von Potatoswatter ist in Ordnung, aber ich bevorzuge es, findoder lower_boundstattdessen zu verwenden. lower_boundDies ist besonders nützlich, da der zurückgegebene Iterator anschließend für eine angedeutete Einfügung verwendet werden kann, falls Sie etwas mit demselben Schlüssel einfügen möchten.

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
quelle
Dies unterscheidet sich geringfügig von der Art und Weise, wie er sagt, dass er es tut. Der einzige Unterschied besteht darin, dass die Berechnung von valuemöglicherweise übersprungen wird, wenn das Einfügen nicht erforderlich ist.
Potatoswatter
1
Klar, ich verstehe, dass es dem OP egal ist, etwas einzufügen, also ist eine auf lower_boundLösungen basierende Lösung übertrieben. Ich habe gerade meine Antwort "der Vollständigkeit halber" erwähnt; Wie ich schon sagte, deine ist vollkommen ausreichend. :-)
Chris Jester-Young
4
Ja, das ist eine gute Antwort und ich bin mit nichts anderer Meinung. Ich möchte nur auf die Beziehung zur Alternative von inserta priori hinweisen . Tatsächlich gibt es einen weiteren Unterschied, wenn bei Verwendung multimapder lower_boundMethode a am Anfang des äquivalenten Bereichs eingefügt wird, während die einfache insertMethode am Ende des Bereichs hinzugefügt wird.
Potatoswatter
2
Nicht die Antwort auf die Frage, aber meine schlechte Frage führte mich hier zur richtigen Antwort ... Ich muss das Einfügen / Aktualisieren durchführen. : D
Hunter-Orionnoir
1
@ Hunter Kannst du mir deinen Code zeigen? Wenn es nicht massiv ist, kann ich es wahrscheinlich für Sie überprüfen.
Chris Jester-Young
8

Ihr Desiderat map.contains(key)ist für den Entwurf des Standards C ++ 2a geplant . 2017 wurde es von gcc 9.2 implementiert . Es ist auch im aktuellen Clang .

Camille Goudeseune
quelle
Das ist eine schöne Funktion! Ich denke, es ist auf C ++ 20 gelandet. cppreference.com
Franklin Yu