El valor de comprobación existe en un std:: map-C++


Sé que find el método encuentra la clave suministrada en std::map y devuelve un iterador al elemento. ¿Hay alguna manera de encontrar el valor y obtener un iterador para el elemento? Lo que necesito hacer es comprobar que el valor especificado existe en std:: map. He hecho esto haciendo un bucle de todos los elementos en el mapa y comparando. Pero quería saber si hay un mejor enfoque para esto.

Esto es lo que he escrito

bool ContainsValue(Type_ value)
{
    bool found = false;
    Map_::iterator it = internalMap.begin(); // internalMap is std::map
    while(it != internalMap.end())
    {
        found = (it->second == value);
        if(found)
            break;
        ++it;
    }
    return found;
}

Editar

Qué tal usar otro mapa internamente que almacena valor, combinación de teclas. ¿Así que puedo llamar a Find on it? Está find() en std::map haciendo una búsqueda secuencial?

Gracias

Author: Eric, 2009-02-11

9 answers

Puede usar boost::multi_index para crear un mapa bidireccional - puede usar cualquier valor del par como clave para hacer una búsqueda rápida.

 20
Author: Mark Ransom,
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
2009-02-11 03:46:00

Si tienes acceso a la excelente biblioteca boost entonces deberías usar boost::multi_index para crear mapa bidireccional como dice Mark. A diferencia de un std:: map, esto le permite buscar por la clave o el valor.

Si solo tiene el STL a mano el siguiente código hará el truco (templada para trabajar con cualquier tipo de mapa donde el mapped_type soporta operator==):

#include <map>
#include <string>
#include <algorithm>
#include <iostream>
#include <cassert>

template<class T>
struct map_data_compare : public std::binary_function<typename T::value_type, 
                                                      typename T::mapped_type, 
                                                      bool>
{
public:
    bool operator() (typename T::value_type &pair, 
                     typename T::mapped_type i) const
    {
        return pair.second == i;
    }
};


int main()
{
    typedef std::map<std::string, int> mapType;

    mapType map;

    map["a"] = 1;
    map["b"] = 2;
    map["c"] = 3;
    map["d"] = 4;
    map["e"] = 5;

    const int value = 3;

    std::map<std::string, int>::iterator it = std::find_if( map.begin(), map.end(), std::bind2nd(map_data_compare<mapType>(), value) );

    if ( it != map.end() )
    {
        assert( value == it->second);
        std::cout << "Found index:" << it->first << " for value:" << it->second << std::endl;
    }
    else
    {
        std::cout << "Did not find index for value:" << value << std::endl;
    }
}
 16
Author: CodeBuddy,
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
2009-05-24 21:52:52

Qué tal usar otro mapa internamente que almacena valor,combinación de teclas. ¿Así que puedo llamar a Find on it?

Sí: mantener dos mapas, con un mapa usando un tipo de clave y el otro usando el otro.

Es find() en std::map haciendo búsqueda secuencial?

No es una búsqueda binaria de un árbol ordenado: su velocidad es O(log(n)).

 15
Author: ChrisW,
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
2009-02-11 03:53:55

Mira los mapas bidireccionales de boost: http://www.boost.org/doc/libs/1_38_0/libs/bimap/doc/html/index.html

Permite que ambos valores actúen como una clave.

De lo contrario, la iteración es el camino a seguir.

 6
Author: Evan Teran,
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
2009-02-11 03:46:55

Prueba esta función:

template <class Map, class Val> typename Map::const_iterator MapSearchByValue(const Map & SearchMap, const Val & SearchVal)
{
    Map::const_iterator iRet = SearchMap.end();
    for (Map::const_iterator iTer = SearchMap.begin(); iTer != SearchMap.end(); iTer ++)
    {
        if (iTer->second == SearchVal)
        {
            iRet = iTer;
            break;
        }
    }
    return iRet;
}

Creo que es útil

 4
Author: Mitch,
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
2011-07-13 19:33:58

No, debe recorrer el mapa std::y verificar todos los valores manualmente. Dependiendo de lo que quieras hacer, podrías envolver el std::map en una clase simple que también almacene en caché todos los valores que se insertan en el mapa en algo que sea fácil de buscar y no permita duplicados, como un std::set. No heredes del mapa std:: (¡no tiene un destructor virtual!), pero envuélvelo para que puedas hacer algo como esto:

WrappedMap my_map< std::string, double >;
my_map[ "key" ] = 99.0;
std::set< double > values = my_map.values(); // should give back a set with only 99.0 in it

Una alternativa a rodar su propia sería a usa el mapa bidireccional de Boost, que se encuentra fácilmente en las publicaciones de abajo o en Google.

Realmente depende de lo que quieras hacer, la frecuencia con la que quieras hacerlo y lo difícil que es rodar tu propia pequeña clase wrapper en lugar de instalar y usar Boost. Me encanta Boost, así que es una buena manera de hacerlo, pero hay algo agradable y completo en hacer tu propia clase de envoltura. Usted tiene la ventaja de comprender directamente la complejidad de las operaciones, y es posible que no necesite la inversión completa mapeo de valores = > claves que proporciona el mapa bidireccional Boost.

 2
Author: James Thompson,
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
2009-02-11 03:47:00

Lo que está solicitando es precisamente lo que std:: find hace (no la función miembro)

template< class InputIt, class T >
InputIt find( InputIt first, InputIt last, const T& value );
 1
Author: AKludges,
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-03-08 14:49:07

No es la mejor opción, pero podría ser útil en algunos casos en los que el usuario asigna un valor predeterminado como 0 o NULL en la inicialización.

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 09:39:56

Es posible que no entienda completamente lo que estás tratando de lograr. Pero para simplemente probar si un mapa contiene o no un valor, creo que puede usar el std::map's construido en find.

bool ContainsValue(Type_ value)
{
    return (internalMap.find(value) != internalMap.end());
}
 -3
Author: Ternary,
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-12-01 19:16:55