c++ - Wie finde ich, ob ein bestimmter Schlüssel in einer C ++ std :: map existiert


Ich versuche zu überprüfen, ob ein gegebener Schlüssel in einer Karte ist und etwas kann es 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 ist?




Answers


Benutze map::find

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



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

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

Die Dokumentation für map::find sagt: "Eine andere Mitgliedsfunktion, map::count , kann verwendet werden, um einfach zu prüfen, ob ein bestimmter Schlüssel existiert."

Die Dokumentation für map::count besagt: "Da alle Elemente in einem Kartencontainer 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 map :: at :

value = m.at(key)

Im Gegensatz zu map :: operator [] erzeugt map::at keinen neuen Schlüssel in der Map, wenn der angegebene Schlüssel nicht existiert.




Sie können .find() :

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

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



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

Wenn Sie eine andere API verwenden möchten, suchen Sie nach 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, Sie wollen map::find . Wenn m.find("f") gleich m.end() , wurde der Schlüssel nicht gefunden. Andernfalls gibt find einen Iterator zurück, der auf das gefundene Element zeigt.

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

Eine Karte kann immer nur ein Element für einen bestimmten Schlüssel haben, daher ist equal_range 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.




Seien Sie vorsichtig beim Vergleichen des Suchergebnisses mit dem Ende wie bei map 'm', da alle Antworten über map :: iterator i = m.find ("f");

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

Sie sollten nicht versuchen, irgendwelche Operationen auszuführen, wie z. B. das Drucken des Schlüssels oder Werts mit Iterator i, wenn er gleich m.end () ist, sonst führt dies zu einem Segmentierungsfehler.




map<string, string> m;

Check-Schlüssel existieren oder nicht, und Return-Nummer von tritt auf (0/1 in Map):

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

Prüfschlüssel existiert oder nicht, und gibt Iterator zurück:

map<string,string>::iterator mi = m.find("f");  
if(mi != m.end()) {  
    //found  
    //do something to mi.  
} else {  
    // not found  
}  

in Ihrer Frage, der Fehler, verursacht durch schlechten operator<< Überlastung, da p.first ist map<string, string> , können Sie es nicht ausdrucken. Versuche dies:

if(p.first != p.second) {
    cout << p.first->first << " " << p.first->second << endl;
}



template <typename T, typename Key>
bool key_exists(const T& container, const Key& key)
{
    return (container.find(key) != std::end(container));
}

Natürlich könnte man, wenn man etwas schicker werden will, immer eine Funktion ausgeben, die auch eine gefundene Funktion und eine nicht gefundene Funktion hat, etwa so:

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

Und benutze es so:

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

Der Nachteil ist ein guter Name, "find_and_execute" ist umständlich und ich kann mir nichts besseres aus dem Kopf machen ...




Wenn ich den Code von std :: map :: find und std :: map :: count vergleiche, würde ich sagen, dass der erste einen gewissen Leistungsvorteil bringt:

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



Wenn Sie ein Kartenpaar vergleichen möchten, können Sie diese Methode verwenden:

typedef map<double, double> TestMap;
TestMap testMap;
pair<map<double,double>::iterator,bool> controlMapValues;

controlMapValues= testMap.insert(std::pair<double,double>(x,y));
if (controlMapValues.second == false )
{
    TestMap::iterator it;
    it = testMap.find(x);

    if (it->second == y)
    {
        cout<<"Given value is already exist in Map"<<endl;
    }
}

Dies ist eine nützliche Technik.