2008-09-26 18 views
6

Cómo configurar todos los valores en una std::map al mismo valor, sin necesidad de utilizar una iteración de un bucle sobre cada valor?Ajuste de todos los valores en un std :: mapa

+0

Torsten, el C++ STL 'map' no está * implementado como una tabla hash. –

Respuesta

13

C++ tiene el método fill de <algorithm> pero esto no funciona para los mapas. De hecho, el soporte de algoritmo para contenedores asociativos generalmente no es bueno.

Como resultado, usted tendrá que usar una iteración o escribir un funtor adecuada para ser utilizada con for_each (pero consideran que esto es una sobrecarga innecesaria):

template <typename TKey, typename TValue> 
struct resetter : public std::unary_function<std::pair<TKey, TValue> > { 
    TValue const value; 

    public resetter(value const& v) : value(v) { } 

    public void operator()(std::pair<TKey, TValue>& v) { 
     v.second = value; 
    } 
}; 

for_each(map.begin(), map.end(), resetter<Key, Value>(value)); 
2

El impulso :: biblioteca de asignación tiene todo tipo de cosas ordenadas para ayudar a inicializar el contenido de un contenedor. Mi idea es que esto podría usarse para evitar iteraciones explícitas a través del mapa. Desafortunadamente, los mapas son bestias curiosas difíciles de inicializar porque las claves deben ser únicas. La conclusión es que un bucle simple es probablemente la mejor manera de inicializar un mapa. Puede que no sea muy elegante, pero hace el trabajo y es inmediatamente comprensible por cualquier persona con cualquier conocimiento de la STL.

map <int,string> myMap; 
for(int k=0;k<1000;k++) 
    myMap.insert(pair<int,string>(k,string(""))); 

El resto de esta publicación describe el viaje que hice para llegar a la conclusión anterior.

El impulso :: Asignar hace que sea sencillo para asignar un número reducido de valores a un mapa.

map<string,int> m; 
insert(m)("Bar", 1)("Foo", 2); 

o

map<int,int> next = map_list_of(1,2)(2,3)(3,4)(4,5)(5,6); 

En su caso, en el que desea inicializar el mapa entero con el mismo valor, no son las utilidades de repetición y repeat_fun.
Algo como esto debería funcionar con un multimap (fragmento de código no probado)

pair<int,string> init(0,string("")); 
multimap <int,string> myMap = repeat(1000,init); 

Como Konrad Rudolph como se ha señalado, no se puede inicializar un mapa con el mismo valor exacto, ya que las claves deben ser únicas.

Esto hace la vida mucho más compleja (divertido?). Algo como esto, tal vez:

map <int,string> myMap; 

struct nextkey 
{ 
    int start; 
    nextkey(s) : start(s) {} 
    pair<int,string> operator()() 
{ 
    return pair<int,string>(start++,string("")); 
} 
}; 

myMap = repeat_fun(1000,nextkey(0)); 

Ahora, esto se está poniendo tan complejo, ahora piensan que una iteración simple es el camino a seguir

map <int,string> myMap; 
for(int k=0;k<1000;k++) 
    myMap.insert(pair<int,string>(k,string(""))); 
+0

el fragmento de código no funcionará en un mapa sencillo porque se inserta la misma tecla de nuevo. Tienes que usar una función de generador en este caso. –

+0

¡Buen punto! Tendría que ser un multimap, o usar repeat_fun. ¿Me pregunto qué quería la pregunta original? – ravenspoint

+0

Sí Boost :: assign es la solución más fácil para llenar mapas. Totalmente de acuerdo, además de la sintaxis es elegante casi como script. –

3

me encontré con el mismo problema, pero encontró que el rango devuelto por boost :: adapters :: values ​​es mutable, por lo que puede usarse con algoritmos normales como std :: fill.

#include <boost/range/adaptor/map.hpp> 
auto my_values = boost::adaptors::values(my_map); 
std::fill(my_values.begin(), my_values.end(), 123); 
Cuestiones relacionadas