¿Determinar si map contiene un valor para una clave?


¿Cuál es la mejor manera de determinar si un mapa STL contiene un valor para una clave dada?

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

}

Examinando esto en un depurador, parece que iter son solo datos basura.

Si descomento esta línea:

Bar b2 = m[2]

El depurador muestra que b2 es {i = 0}. (Supongo que significa que el uso de un índice indefinido devolverá una estructura con todos los valores vacíos/no inicializados?)

Ninguno de estos métodos es tan grande. Lo que realmente me gustaría es una interfaz como esto:

bool getValue(int key, Bar& out)
{
    if (map contains value for key)
    {
        out = map[key];
        return true;
    }
    return false;
}

¿Existe algo en este sentido?

 187
Author: jww, 2010-06-29

9 answers

¿Existe algo en este sentido?

No. Con la clase de mapa stl, se utiliza ::find() para buscar en el mapa, y comparar el iterador devuelto a std::map::end()

So

map<int,Bar>::iterator it = m.find('2');
Bar b3;
if(it != m.end())
{
   //element found;
   b3 = it->second;
}

Obviamente puedes escribir tu propia rutina getValue() si quieres (también en C++, no hay razón para usar out), pero sospecho que una vez que aprendas a usar std::map::find() no querrás perder el tiempo.

También su código es ligeramente mal:

m.find('2'); buscará en el mapa un valor clave que sea '2'. IIRC el compilador de C++ convertirá implícitamente '2' a un int, lo que resulta en el valor numérico para el código ASCII para '2' que no es lo que desea.

Desde su keytype en este ejemplo es int desea buscar como este: m.find(2);

 205
Author: Alan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-10-20 21:24:41

Mientras el mapa no sea un multimap, una de las formas más elegantes sería usar el método de conteo

if (m.count(key))
    // key exists

El recuento sería 1 si el elemento está efectivamente presente en el mapa.

 260
Author: pconnell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-03-05 23:29:47

Ya existe con find solo que no en esa sintaxis exacta.

if (m.find(2) == m.end() )
{
    // key 2 doesn't exist
}

Si desea acceder al valor si existe, puede hacer:

map<int, Bar>::iterator iter = m.find(2);
if (iter != m.end() )
{
    // key 2 exists, do something with iter->second (the value)
}

Con C++0x y auto, la sintaxis es más simple:

auto iter = m.find(2);
if (iter != m.end() )
{
    // key 2 exists, do something with iter->second (the value)
}

Le recomiendo que se acostumbre a él en lugar de tratar de llegar a un nuevo mecanismo para simplificarlo. Es posible que pueda reducir un poco el código, pero considere el costo de hacerlo. Ahora ha introducido una nueva función que las personas familiarizadas con C++ no podrán reconocer.

Si desea implementar esto de todos modos a pesar de estas advertencias, entonces:

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;
}
 45
Author: stinky472,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-06-28 22:16:30

amap.find devuelve amap::end cuando no encuentra lo que está buscando supposed se supone que debe verificar eso.

 5
Author: Alex Martelli,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-06-28 22:13:45

Compruebe el valor devuelto de find frente a end.

map<int, Bar>::iterator it = m.find('2');
if ( m.end() != it ) { 
  // contains
  ...
}
 4
Author: JaredPar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-24 22:54:54

Acabo de notar que con C++20, tendremos

std::map::contains( const Key& key ) const;

Que devolverá true si map contiene un elemento con clave key.

 3
Author: kebs,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-25 22:08:25

Puede crear su función getValue con el siguiente código:

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
Author: Kip Streithorst,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-08 22:50:55

Si desea determinar si hay una clave en map o no, puede usar la función miembro find() o count() de map. La función find que se usa aquí en el ejemplo devuelve el iterador a element o map:: end de lo contrario. En el caso de count el count devuelve 1 si se encuentra, de lo contrario devuelve cero(o de lo contrario).

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;
}
 1
Author: Prashant Shubham,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-07-30 08:05:49

Boost multindex se puede utilizar para la solución adecuada. La siguiente solución no es la mejor opción, pero puede ser útil en algunos casos en los que el usuario asigna un valor predeterminado como 0 o NULL en la inicialización y desea verificar si el valor se ha modificado.

Ex.
< int , string >
< string , int > 
< string , string > 

consider < string , string >
mymap["1st"]="first";
mymap["second"]="";
for (std::map<string,string>::iterator it=mymap.begin(); it!=mymap.end(); ++it)
{
       if ( it->second =="" ) 
            continue;
}
 0
Author: user2761565,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-06 10:23:43