Wie lässt sich am besten feststellen, ob eine STL-Zuordnung einen Wert für einen bestimmten Schlüssel enthält?
#include <map>
using namespace std;
struct Bar
{
int i;
};
int main()
{
map<int, Bar> m;
Bar b = {0};
Bar b1 = {1};
m[0] = b;
m[1] = b1;
//Bar b2 = m[2];
map<int, Bar>::iterator iter = m.find(2);
Bar b3 = iter->second;
}
Betrachtet man dies in einem Debugger, sieht es so aus, als ob iter
nur Mülldaten sind.
Wenn ich diese Zeile auskommentiere:
Bar b2 = m[2]
Der Debugger zeigt, dass b2
ist {i = 0}
. (Ich vermute, es bedeutet, dass die Verwendung eines undefinierten Index eine Struktur mit allen leeren/nicht initialisierten Werten zurückgibt?)
Keine dieser Methoden ist so toll. Was ich wirklich gerne hätte, ist eine Benutzeroberfläche wie diese:
bool getValue(int key, Bar& out)
{
if (map contains value for key)
{
out = map[key];
return true;
}
return false;
}
Gibt es etwas in dieser Richtung?
Gibt es etwas in dieser Richtung?
Nein. In der Klasse stl map verwenden Sie ::find()
, um die Karte zu durchsuchen und den zurückgegebenen Iterator mit std::map::end()
zu vergleichen.
damit
map<int,Bar>::iterator it = m.find('2');
Bar b3;
if(it != m.end())
{
//element found;
b3 = it->second;
}
Natürlich können Sie Ihre eigene getValue()
-Routine schreiben, wenn Sie möchten (auch in C++ gibt es keinen Grund, out
zu verwenden), aber ich würde vermuten, dass Sie, sobald Sie den Dreh raus haben, std::map::find()
Sie wollen Ihre Zeit nicht verschwenden.
Auch Ihr Code ist leicht falsch:
m.find('2');
durchsucht die Map nach einem Schlüsselwert, der '2'
lautet. IIRC Der C++ - Compiler konvertiert implizit '2' in ein int, was den numerischen Wert für den ASCII Code für '2' ergibt, der nicht Ihren Wünschen entspricht.
Da Ihr Schlüsseltyp in diesem Beispiel int
ist, möchten Sie folgendermaßen suchen: m.find(2);
Solange es sich bei der Karte nicht um eine Multimap handelt, ist die Zählmethode eine der elegantesten Methoden
if (m.count(key))
// key exists
Die Anzahl wäre 1, wenn das Element tatsächlich in der Karte vorhanden ist.
Es existiert bereits mit find nur nicht in der exakten Syntax.
if (m.find(2) == m.end() )
{
// key 2 doesn't exist
}
Wenn Sie auf den Wert zugreifen möchten, falls er vorhanden ist, können Sie Folgendes tun:
map<int, Bar>::iterator iter = m.find(2);
if (iter != m.end() )
{
// key 2 exists, do something with iter->second (the value)
}
Mit C++ 0x und auto ist die Syntax einfacher:
auto iter = m.find(2);
if (iter != m.end() )
{
// key 2 exists, do something with iter->second (the value)
}
Ich empfehle Ihnen, sich daran zu gewöhnen, anstatt sich einen neuen Mechanismus auszudenken, um ihn zu vereinfachen. Möglicherweise können Sie ein bisschen Code einsparen, aber bedenken Sie die Kosten dafür. Jetzt haben Sie eine neue Funktion eingeführt, die mit C++ vertraute Personen nicht erkennen können.
Wenn Sie dies trotz dieser Warnungen trotzdem umsetzen wollen, dann:
template <class Key, class Value, class Comparator, class Alloc>
bool getValue(const std::map<Key, Value, Comparator, Alloc>& my_map, int key, Value& out)
{
typename std::map<Key, Value, Comparator, Alloc>::const_iterator it = my_map.find(key);
if (it != my_map.end() )
{
out = it->second;
return true;
}
return false;
}
Mir ist gerade aufgefallen, dass wir mit C++ 2 haben werden
std::map::contains( const Key& key ) const;
Dies gibt true zurück, wenn map ein Element mit dem Schlüssel key
enthält.
amap.find
kehrt zurück amap::end
Wenn es nicht das findet, wonach Sie suchen, sollten Sie das überprüfen.
Überprüfen Sie den Rückgabewert von find
gegen end
.
map<int, Bar>::iterator it = m.find('2');
if ( m.end() != it ) {
// contains
...
}
Um einige der anderen Antworten kurz zusammenzufassen:
Wenn Sie C++ 20 noch nicht verwenden, können Sie Ihre eigene mapContainsKey
-Funktion schreiben:
bool mapContainsKey(std::map<int, int>& map, int key)
{
if (map.find(key) == map.end()) return false;
return true;
}
Wenn Sie viele Überladungen für map
vs unordered_map
Und verschiedene Schlüssel- und Werttypen vermeiden möchten, können Sie dies zu einer template
-Funktion machen.
Wenn Sie C++ 20
Oder höher verwenden, gibt es eine integrierte Funktion contains
:
std::map<int, int> myMap;
// do stuff with myMap here
int key = 123;
if (myMap.contains(key))
{
// stuff here
}
Sie können Ihre getValue-Funktion mit dem folgenden Code erstellen:
bool getValue(const std::map<int, Bar>& input, int key, Bar& out)
{
std::map<int, Bar>::iterator foundIter = input.find(key);
if (foundIter != input.end())
{
out = foundIter->second;
return true;
}
return false;
}
Wenn Sie feststellen möchten, ob ein Schlüssel in der Karte vorhanden ist oder nicht, können Sie die Elementfunktion find () oder count () der Karte verwenden. Die hier im Beispiel verwendete Suchfunktion gibt den Iterator ansonsten an element oder map :: end zurück. Im Fall von count gibt der Zähler 1 zurück, wenn er gefunden wird, andernfalls null (oder anders).
if(phone.count(key))
{ //key found
}
else
{//key not found
}
for(int i=0;i<v.size();i++){
phoneMap::iterator itr=phone.find(v[i]);//I have used a vector in this example to check through map you cal receive a value using at() e.g: map.at(key);
if(itr!=phone.end())
cout<<v[i]<<"="<<itr->second<<endl;
else
cout<<"Not found"<<endl;
}