So finden Sie heraus, ob ein bestimmter Schlüssel in einer C++ std::map vorhanden ist

Lesezeit: 7 Minuten

Benutzer-Avatar
Wir können nichts tun

Ich versuche zu überprüfen, ob sich ein bestimmter Schlüssel in einer Karte befindet, und kann dies irgendwie nicht tun:

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

Wie kann ich also drucken, was in p steht?

  • std::pair<iterator,bool> insert( const value_type& value ); Was ist der Bool, den es zurückgibt? sagt es, ob der Schlüssel bereits vorhanden ist oder nicht?

    – krithikaGopalakrisnan

    28. März 2019 um 7:00 Uhr

Benutzen map::find

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

  • Wenn Sie nur überprüfen möchten, ob ein bestimmter Schlüssel vorhanden ist, verwenden Sie wahrscheinlich lieber map::count

    – tomsmeding

    28. August 2013 um 16:17 Uhr

  • @tomsmeding Es gibt nur einen einzigen Schlüssel in einer std::map. Die Anzahl ist also entweder 0 oder 1. Ist einer effizienter als der andere?

    – Gulasch

    17. Juli 2015 um 7:38 Uhr

  • @goelakash kaum; es ist nur so dass count gibt ein zurück int während find gibt einen ganzen Iterator zurück. Du sparst dir den Bau des Iterators 🙂 Offensichtlich, wenn du danach gehst benutzen den Wert, falls vorhanden, verwenden Sie find und speichern Sie das Ergebnis.

    – tomsmeding

    17. Juli 2015 um 8:04 Uhr


  • @tomsmeding Wenn Sie eine Multimap verwenden, müssen Sie den gesamten Container durchsuchen. In diesem Fall kann find() schneller sein.

    – Trevor Hickey

    21. September 2016 um 18:03 Uhr

  • Für diejenigen, die Geschwindigkeit suchen: count und find sind nahezu identisch in der Geschwindigkeit, wenn Karten verwendet werden, die eindeutige Schlüssel erfordern. (1) Wenn Sie die Elemente nicht benötigen, um eine bestimmte Reihenfolge beizubehalten, verwenden Sie std::unordered_map, das nahezu konstante Lookups hat und sehr nützlich sein kann, wenn mehr als ein paar Paare gespeichert werden. (2) Wenn Sie den Wert verwenden möchten, falls vorhanden, speichern Sie das Ergebnis von ::find und verwenden Sie den Iterator, um 2 Suchen zu verhindern: auto it = m.find("f"); if (it != m.end()) {/*Use it->second*/}

    – cdgraham

    19. März 2019 um 17:55 Uhr


Benutzer-Avatar
DavidRR

Um zu überprüfen, ob ein bestimmter Schlüssel in der Karte vorhanden ist, verwenden Sie die count Mitgliedsfunktion auf eine der folgenden Arten:

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

Das Dokumentation zum map::find sagt: “Eine weitere Elementfunktion, map::countkann verwendet werden, um nur zu prüfen, ob ein bestimmter Schlüssel vorhanden ist.”

Das Dokumentation zum map::count sagt: “Da alle Elemente in einem Map-Container eindeutig sind, kann die Funktion nur 1 (wenn das Element gefunden wird) oder Null (andernfalls) zurückgeben.”

Um einen Wert aus der Karte über einen Schlüssel abzurufen, von dem Sie wissen, dass er existiert, verwenden Sie Karte::at:

value = m.at(key)

nicht wie map::operator[], map::at erstellt keinen neuen Schlüssel in der Zuordnung, wenn der angegebene Schlüssel nicht vorhanden ist.

  • Wenn Sie beide Vorgänge ausführen möchten, überprüfen Sie, ob es vorhanden ist, und unternehmen Sie dann etwas dagegen. Benutzen find stattdessen. Das second Attribut des Iterators, der von zurückgegeben wird find kann verwendet werden, um den Wert des Schlüssels abzurufen. Wenn du benutzt count dann at oder operator[] Sie führen zwei Operationen durch, wenn Sie nur eine hätten verwenden können.

    – OdraEncoded

    13. Juni 2014 um 21:24 Uhr

  • Sie brauchen nicht > 0, == 1 oder != 0; das ist die genaue Prüfung, die C++ in einer if-Anweisung durchführt (Bedingung != 0), also können Sie einfach verwenden if(m.count(key))

    – jv110

    16. Dezember 2016 um 20:50 Uhr

  • @jv110 Der Microsoft C++-Compiler gibt eine Warnung aus, wenn er auf eine Umwandlung von trifft int zu bool. Obwohl es andere C++-Compiler gibt, die keine ähnliche Warnung ausgeben, bevorzuge ich die Verwendung eines expliziten Vergleichs, um die Absicht klar zu machen und die Lesbarkeit zu verbessern. Beachten Sie, dass andere Sprachen wie C# eine solche implizite Konvertierung verbieten, um die Möglichkeit zu verhindern, subtile Programmierfehler einzuführen.

    – DavidRR

    17. Dezember 2016 um 15:38 Uhr

  • @Mazeryt Angesichts der Tatsache, dass es sich um eine Klasse in der C++-Standardbibliothek handelt, würde ich davon ausgehen. Eine sprachunabhängige Diskussion Ihrer Frage finden Sie unter Können Hashtabellen wirklich O(1) sein?.

    – DavidRR

    14. Mai 2017 um 15:10 Uhr


  • @ Mazeryt Nein, std::map::count ist eigentlich logarithmisch. Das ist weil C++ std::map ist eine geordnete Karte, verwendet also keine Hash-Tabelle. Die C++-Standardbibliothek hat jedoch auch std::unordered_mapwo std::unordered_map::count ist O(1) oft. Sehen Sie sich den Link von DavidRR an, um zu erfahren, warum sogar std::unordered_map::count nicht immer O(1) ist.

    – cdgraham

    19. März 2019 um 17:32 Uhr

C++20 gibt uns std::map::contains das zu tun.

#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";
    }
}

  • Ich denke, ich werde es sagen: Endlich.

    – Erik Campobadal

    14. Februar 2019 um 21:54 Uhr

  • Toll! Gut, dass ich hier runter gescrollt habe. Vielleicht die akzeptierte Antwort bearbeiten und hinzufügen?

    – Roozbeh Sayadi

    26. April um 17:28 Uhr

Sie können verwenden .find():

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

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

Benutzer-Avatar
WBuck

C++17 Vereinfachte dies etwas mehr mit an If statement with initializer. Auf diese Weise können Sie Ihren Kuchen haben und ihn auch essen.

if ( auto it{ m.find( "key" ) }; it != std::end( m ) ) 
{
    // Use `structured binding` to get the key
    // and value.
    const 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.
    const auto& mkey{ it->first };
    const auto& mvalue{ it->second };

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

Benutzer-Avatar
aJ.

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

Wenn Sie eine andere API verwenden möchten, suchen Sie go for 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";

Ich denke, du willst map::find. Ob m.find("f") entspricht m.end(), dann wurde der Schlüssel nicht gefunden. Andernfalls gibt find einen Iterator zurück, der auf das gefundene Element zeigt.

Der Fehler liegt daran p.first ist ein Iterator, der nicht für das Einfügen von Streams funktioniert. Ändern Sie Ihre letzte Zeile in cout << (p.first)->first;. p ist ein Paar Iteratoren, p.first ist ein Iterator, p.first->first ist die Schlüsselkette.

Eine Karte kann also immer nur ein Element für einen bestimmten Schlüssel haben equal_range ist nicht sehr nützlich. Es ist für map definiert, weil es für alle assoziativen Container definiert ist, aber es ist viel interessanter für multimap.

  • Da es sich um ein Paar Iteratoren für eine Map handelt, sollte es eigentlich “cout << p.first->first;” sein.

    – stefaanv

    21. Dezember 2009 um 13:06 Uhr

  • Ich habe meine Antwort korrigiert, danke. Das bekomme ich, wenn ich meinen Code nicht kompiliere. Und Sie haben (in einem gelöschten Kommentar) Recht, die Gültigkeit zu überprüfen, aber ich habe nur versucht zu erklären, warum er p.first nicht drucken konnte, und das liegt nicht daran, dass es ungültig ist – wir wissen, dass “f” gefunden wird. Da ich die Verwendung von equal_range überhaupt nicht empfehle, werde ich dafür keinen Code zur Fehlerprüfung zeigen.

    – Steve Jessop

    21. Dezember 2009 um 13:12 Uhr

  • Wow, du scannst wirklich SO. Ich habe es nur der Vollständigkeit halber hinzugefügt, weil Ihr Punkt klar war. Ich habe die Gültigkeitsprüfung zu meiner vorherigen Antwort hinzugefügt, aber Ihre Antwort hat mich geschlagen, also habe ich sie gelöscht, weil sie, wie Sie erwähnt haben, sowieso nicht so viel hinzugefügt hat.

    – stefaanv

    21. Dezember 2009 um 16:10 Uhr

  • Ja, ich habe es überhaupt nur gesehen, weil Ihr Kommentar erschien, als ich meinen gepostet habe.

    – Steve Jessop

    21. Dezember 2009 um 17:16 Uhr

1013260cookie-checkSo finden Sie heraus, ob ein bestimmter Schlüssel in einer C++ std::map vorhanden ist

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy