Карта STL внутри карты С++

В С++-карте STL у меня есть определение типа

   map<string, map<int, string> >;

и я итерации, используя следующий код.

   for( map<string, map<int, string> >::iterator ii=info.begin(); ii!=info.end(); ++ii){
       for(map<int, string>::iterator j=ii->second.begin(); j!=ii->second.end();++j){
           cout << (*ii).first << " : " << (*j).first << " : "<< (*j).second << endl;
       }
   }

Мое сомнение в том, что это правильный способ повторения или есть лучший способ сделать это? Вышеприведенный код работает для меня. Но m ищет более элегантное решение.

Ответ 1

Это правильно, просто не хватает нескольких typedef и улучшений читаемости:

typedef std::map<int, std::string> inner_map;
typedef std::map<std::string, inner_map> outer_map;

for (outer_map::iterator i = outerMap.begin(), iend = outerMap.end(); i != iend; ++i)
{
    inner_map &innerMap = i->second;
    for (inner_map::iterator j = innerMap.begin(), jend = innerMap.end(); j != jend; ++j)
    {
        /* ... */
    }
}

Ответ 2

Если доступен С++ 11, вы можете использовать цикл for:

for(auto &i: info) {
    for(auto &j: i.second) {
        /* */
    }
}

Если доступен только С++ 11 auto:

for( auto i=info.begin(); i!=info.end(); ++i) {
   for( auto j=i->second.begin(); j!=i->second.end(); ++j) {
       /* */
   }
}

Если вы можете использовать BOOST, BOOST_FOREACH:

typedef std::map<int, std::string> inner_map;
typedef std::map<std::string, inner_map> outer_map;

outer_map outer;

BOOST_FOREACH(outer_map::value_type &outer_value, outer){
    BOOST_FOREACH(inner_map::value_type &inner_value, outer_value->second){
        /* use outer_value and inner_value as std::pair */
    }
}

Ответ 3

Пока непонятно, какую проблему вы решаете, имея карту внутри карты, я не думаю, что есть лучший способ повторить все элементы без использования этих итераторов. Единственное, что вы можете сделать для улучшения чтения кода, - это использование typedefs в типах шаблонов.

Однако, не лучше ли определить ваш map как

multimap <string, MyClass>

где MyClass определяется как пара целых чисел и строка, а также метод toString() для сброса содержимого и т.д.?

Ответ 4

Если С++ 11 доступен, мы могли бы использовать stl-алгоритм for_each и лямбда-функций для получения элегантного решения

typedef map<int, string> INNERMAP;
typedef map<string, INNERMAP> OUTERMAP;

OUTERMAP theMapObject;
// populate the map object

//итерация объекта карты теперь

std::for_each(theMapObject.cbegin(), theMapObject.cend(), 
    [](const OUTERMAP::value_type& outerMapElement)
{
    // process the outer map object
    const INNERMAP& innerMapObject = outerMapElement.second;
    std::for_each(innerMapObject.cbegin(), innerMapObject.cend(), 
        [](const INNERMAP::value_type& innermapElemen)
    {
        //process the inner map element
    });
});

Ответ 5

Если вы хотите итерации по обеим картам, то наилучшим способом является то, как вы представляли. Теперь, если есть что-то конкретное, которое вы хотите сделать, вам может быть лучше использовать функцию из заголовка алгоритма.