Wie finde ich den kleinsten Wert in einer map?
Ich habe eine map
und ich möchten, finden Sie den minimalen Wert (rechts) in der Karte. Hier ist, wie ich es gemacht habe:
bool compare(std::pair<std::string ,int> i, pair<std::string, int> j) {
return i.second < j.second;
}
////////////////////////////////////////////////////
std::map<std::string, int> mymap;
mymap["key1"] = 50;
mymap["key2"] = 20;
mymap["key3"] = 100;
std::pair<char, int> min = *min_element(mymap.begin(), mymap.end(), compare);
std::cout << "min " << min.second<< " " << std::endl;
Den code oben funktioniert einwandfrei und ich bin in der Lage, um den minimalen Wert. Allerdings, wenn ich diesen code in meine Klasse wie folgt, es scheint nicht zu funktionieren:
int MyClass::getMin(std::map<std::string, int> mymap) {
std::pair<std::string, int> min = *min_element(mymap.begin(), mymap.end(),
(*this).compare);
//Error probably due to "this".
return min.second;
}
bool MyClass::compare(
std::pair<std::string, int> i, std::pair<std::string, int> j) {
return i.second < j.second;
}
Wie kann ich den code mit meiner Klasse? Außerdem gibt es eine bessere Lösung, die nicht bedürfen der Schriftform die weitere compare
Funktion?
- Die Funktion getMin sollte vorbei das argument mit der const-Referenz und nicht als Wert. Auch Sie haben ein problem, wenn die Karte hat keine Elemente überhaupt, so denken Sie daran, nicht dereferecing der iterator vor makig sicher, dass end() zurückgegeben wird.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Haben Sie ein paar Optionen. Der "beste" Weg, dies zu tun ist mit einem Funktor, das ist garantiert der Schnellste zu sein, zu rufen:
(Sie können auch nest die
CompareSecond
Klasse inMyClass
.Mit dem code, den Sie jetzt haben, können Sie leicht ändern Sie es zu arbeiten, jedoch. Stellen Sie einfach die Funktion
static
und die richtige syntax verwenden:operator()
statt für die gesamte Klasse... das ist der beste Weg, yeah :vP .operator()
werden sollte, vorgefertigte best practice. Aber ich denke, der code soll veranschaulichen den Punkt. Was meinst du mit "geben Sie die template-Argumente"? Meinst du ableiten vonbinary_function
? Ich glaube nicht, dass es erforderlich istmin_element
...In C++11 können Sie dies tun:
Oder legen Sie es in eine nette Funktion wie folgt aus (beachten Sie, ich bin nicht eine Vorlage guru; dies ist wohl falsch in vielerlei Hinsicht):
Mit C++14, weiter vereinfacht zu:
auto
für die parameter-Typenl
undr
. Das erfordert C++14, jedoch.Das problem ist, dass diese:
Erfordert eine Instanz der Klasse aufgerufen werden. Das heißt, Sie können nicht einfach anrufen
MyClass::compare
, aber Sie müssensomeInstance.compare
. Allerdingsmin_element
muss der ehemalige.Die einfache Lösung ist, um es
static
:Dies ist nicht mehr erforderlich, eine Instanz aufgerufen werden, und Ihr code wird in Ordnung sein. Sie können machen es die mehr der Regel mit einem Funktor, wenn:
All dies tut, ist schnappen Sie sich den zweiten von jedem paar und Sie greifen, funktioniert mit jedem paar. Es könnte gemacht werden für Allgemeine, aber das ist ein bisschen zu viel.
Wenn Sie nachschlagen müssen Wert genug ist, empfehle ich Euch die Verwendung von Boost ist Bimap. Es ist eine bi-direktionale anzeigen, also beide den Schlüssel und den Wert kann verwendet werden, um nachschlagen. Einfach die front der value-Taste anzeigen.
Schließlich können Sie immer verfolgen Sie die minimalen Elemente in Ihre Karte. Jedes mal, wenn Sie legen Sie einen neuen Wert ein, prüfen Sie, ob es niedriger ist als Ihr Aktueller Wert (und das sollte wahrscheinlich ein Zeiger auf einen map-pair-Mädchen, starten Sie es als null), und wenn es niedriger ist, zeigen Sie auf die neue niedrigste. Die Beantragung der niedrigsten wird so einfach wie das dereferenzieren eines Zeigers.
Ich habe eigentlich eine andere Frage: wenn Sie regelmäßig erhalten, ist das minimum der rechten Seite Werte, sind Sie sicher, dass als ein
map
ist die beste Struktur ?Ich würde vorschlagen, mit
Boost.MultiIndex
im Allgemeinen für diese Probleme von mehreren Möglichkeiten der Indexierung den gleichen Satz von Objekten... aber wenn Sie müssen nur dieses "reverse-mapping" bitBoost.Bimap
könnte sich als einfacher erweisen.Diese Weise werden Sie nicht haben eine lineare Suche das minimum 🙂
C++14
Wie bereits in Jonathan Geisler ' s Kommentar auf Timmmm Antwort, C++14 ermöglicht lambda-Funktion Parameter deklariert werden, mit der
auto
Typ Bezeichner. Als Ergebnis, können Sie verkürzen Timmmm ist die lambda-basiertemin_element
Linie (und zur Verbesserung seiner Lesbarkeit) wie folgt:Hinweis 1: Wenn Sie diese Zeile in Ihre
MyClass::getMin()
Funktion, Sie müssen zurückit->second
. Jedoch, zu berücksichtigen, für eine leere Karte, die Sie anpassen sollten, diereturn
Zeile wie folgt (oder ähnlich):Hinweis 2: Wie auch erwähnt Lance Diduck, sollten Sie die übergabe der Karte durch
const
Verweis auf IhregetMin()
Funktion. Die Art und Weise Sie es getan haben, erstellen Sie eine unnötige Kopie der gesamten Karte.Code auf Ideone