2012-03-30 15 views
15

estoy inicializando map<string, vector<string> > de la siguiente manera:inicializar mapa <cadena, vector <string>>

map <string, vector<string> > dict; 

dict["USA"].push_back("NYC"); 
dict["USA"].push_back("LA"); 
dict["USA"].push_back("Chicago"); 
dict["USA"].push_back("Dallas"); 

dict["India"].push_back("Delhi"); 
dict["India"].push_back("Bombay"); 

dict["Australia"].push_back("Melbourne"); 
dict["Australia"].push_back("Sydney"); 
dict["Australia"].push_back("Adelaide"); 

Me parece engorroso. Lo mismo se puede hacer de la siguiente manera tcl que es más limpio:

array set dict { 
USA {NYC LA Chicago Dallas} 
India {Delhi Bombay} 
Australia {Melbourne Sydney Adelaide} 
} 

¿Existe una manera más limpia para inicializar en C++? Mi compilador es gcc 3.4.6

+7

En C++ 11, sí. En GCC 3.4.6, no. – Pubby

+2

GCC 3.4.6 ??? Deberías considerar actualizar a un compilador más nuevo ... Hay una biblioteca de impulso para facilitar este tipo de inicialización, pero no estoy seguro de que pueda usarse con un compilador tan antiguo (6 años es casi una eternidad) –

Respuesta

6

Si no tiene miedo de usar un poco de macros C-style y algunas construcciones auxiliares, puede encontrar esto un poco menos irritable; la inicialización del mapa se hace en una línea; solo necesita completar los datos (lo cual debe hacer de todos modos).

#include <iostream> 
#include <map> 
#include <vector> 
#include <string> 
#include <utility> 

using namespace std; 

struct entry { 
    string key; 
    string* vals; 
    size_t nvals; 
}; 
#define NVAL(x) (sizeof(x)/sizeof(x[0])) 

int main(void) { 
    // Create your data 
    string  usa[]  = {"NYC", "LA"}; 
    string  india[] = {"Delhi", "Mumbai"}; 
    entry  dd[] = { 
          {"USA", usa, NVAL(usa)}, 
          {"India", india, NVAL(india)} 
         }; 
    map<string, vector<string> > dict; 

    // initialize the map 
    for(unsigned int i=0; i<NVAL(dd); i++) 
     dict.insert(make_pair(dd[i].key, vector<string>(dd[i].vals, dd[i].vals+dd[i].nvals))); 

    // Verify 
    for(map<string,vector<string> >::const_iterator ptr=dict.begin(); 
     ptr!=dict.end(); ptr++) { 
     cout << ptr->first << ": "; 
     for(vector<string>::const_iterator eptr=ptr->second.begin(); 
      eptr!=ptr->second.end(); eptr++) 
       cout << *eptr << " "; 
     cout << endl; 
    } 
    return 0; 
} 
+0

Su macro se puede reemplazar trivialmente con una plantilla de función: 'template std :: size_t NVAL (T (&) [N]) {return N; } ' – ildjarn

+0

¡De hecho, es una solución elegante! ¡Gracias! – haavee

25

La inicialización tenía muchas limitaciones en el viejo C++. Su código, de hecho, no está inicializando nada en absoluto; simplemente llama a muchas funciones miembro en un objeto ya inicializado.

En la actual C++ (C++ 11) que puede inicializar correctamente su mapa:

std::map<std::string, std::vector<std::string>> const dict { 
    { "USA", { "NYC", "LA", "Chicago" } }, 
    { "India", { "Delhi", "Bombay" } } 
}; 
+4

oh dios, ¡esto es hermoso! – innochenti

+2

Realmente es una lástima que les tomó ~ 15 años para llegar a él: P – haavee

+0

Ah, y OP dijo que su compilador es g ++ 3.4.6, que está muy lejos de C++ 11 - publicando así soluciones elegantes que el OP no puede usar podría no ser tan útil ... ¡ay! – haavee

8

usted puede hacer esto, si C++ 11 no está disponible:

map <string, vector<string> > dict; 

string usa[] = { "NYC" , "LA" , "Chicago" , "Dallas" }; 
dict["USA"] = std::vector<string>(usa,usa+4); 
8

Si usted no está en lugar de utilizar la biblioteca Boost.Assign y está utilizando C++ mayores de 11 C++, puede hacerlo de esta manera:

#include <boost/assign/list_of.hpp> 
#include <boost/assign/std/vector.hpp> 
#include <map> 
#include <string> 
#include <vector> 

std::map<std::string, vector<std::string> > dict = boost::assign::map_list_of<std::string, std::vector<std::string> > 
    ("USA", boost::assign::list_of<std::string>("NYC")("LA")("Chicago")("Dallas")) 
    ("India", boost::assign::list_of<std::string>("Delhi")("Bombay")) 
; 
Cuestiones relacionadas