Инициализация карты <строка, вектор <строкa>>
Я инициализирую map<string, 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");
Я нахожу это громоздким. То же самое можно сделать в tcl
следующим образом, что является более чистым:
array set dict {
USA {NYC LA Chicago Dallas}
India {Delhi Bombay}
Australia {Melbourne Sydney Adelaide}
}
Есть ли более чистый способ инициализации в C++
? Мой компилятор gcc 3.4.6
Ответы
Ответ 1
Если вы не боитесь использовать немного макросов C-стиля и некоторые вспомогательные конструкции, вы можете обнаружить, что это немного менее раздражительно; инициализация карты выполняется в одной строке; вам нужно всего лишь заполнить данные (которые вы должны делать в любом случае).
#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;
}
Ответ 2
Инициализация имела множество ограничений в старом С++. Ваш код на самом деле ничего не инициализирует; он просто вызывает множество функций-членов на уже инициализированном объекте.
В текущем С++ (С++ 11) вы можете правильно инициализировать свою карту:
std::map<std::string, std::vector<std::string>> const dict {
{ "USA", { "NYC", "LA", "Chicago" } },
{ "India", { "Delhi", "Bombay" } }
};
Ответ 3
Вы можете сделать это, если С++ 11 недоступен:
map <string, vector<string> > dict;
string usa[] = { "NYC" , "LA" , "Chicago" , "Dallas" };
dict["USA"] = std::vector<string>(usa,usa+4);
Ответ 4
Если вы не против использования библиотеки Boost.Assign и используете С++ старше С++ 11, вы можете сделать это следующим образом:
#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"))
;