wake-up-neo.com

Bestimmen, ob die Karte einen Wert für einen Schlüssel enthält?

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?

219
Nick Heiner

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

241
Alan

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.

293
pconnell

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;
}
50
stinky472

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.

19
kebs

amap.find kehrt zurück amap::end Wenn es nicht das findet, wonach Sie suchen, sollten Sie das überprüfen.

7
Alex Martelli

Überprüfen Sie den Rückgabewert von find gegen end.

map<int, Bar>::iterator it = m.find('2');
if ( m.end() != it ) { 
  // contains
  ...
}
4
JaredPar

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
}
1
cdahms

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;
}
1
Kip Streithorst

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