如何循环C ++地图的地图?

如何在C ++中循环使用
std::map
?我的地图定义为:
std::map< std::string, std::map<std::string, std::string> >
例如,上面的容器包含如下数据:
m["name1"]["value1"] = "data1";
m["name1"]["value2"] = "data2";
m["name2"]["value1"] = "data1";
m["name2"]["value2"] = "data2";
m["name3"]["value1"] = "data1";
m["name3"]["value2"] = "data2";
如何遍历此地图并访问各种值?     
已邀请:
旧的问题,但剩下的答案已经过时了C ++ 11 - 您可以使用基于范围的for循环,只需执行:
std::map<std::string, std::map<std::string, std::string>> mymap;

for(auto const &ent1 : mymap) {
  // ent1.first is the first key
  for(auto const &ent2 : ent1.second) {
    // ent2.first is the second key
    // ent2.second is the data
  }
}
这应该比早期版本更清晰,并避免不必要的副本。 有人赞成用引用变量的明确定义替换注释(如果未使用则会被优化掉):
for(auto const &ent1 : mymap) {
  auto const &outer_key = ent1.first;
  auto const &inner_map = ent1.second;
  for(auto const &ent2 : inner_map) {
    auto const &inner_key   = ent2.first;
    auto const &inner_value = ent2.second;
  }
}
    
您可以使用迭代器。
typedef std::map<std::string, std::map<std::string, std::string>>::iterator it_type;
for(it_type iterator = m.begin(); iterator != m.end(); iterator++) {
    // iterator->first = key
    // iterator->second = value
    // Repeat if you also want to iterate through the second map.
}
    
for(std::map<std::string, std::map<std::string, std::string> >::iterator outer_iter=map.begin(); outer_iter!=map.end(); ++outer_iter) {
    for(std::map<std::string, std::string>::iterator inner_iter=outer_iter->second.begin(); inner_iter!=outer_iter->second.end(); ++inner_iter) {
        std::cout << inner_iter->second << std::endl;
    }
}
或者在C ++ 0x中更好:
for(auto outer_iter=map.begin(); outer_iter!=map.end(); ++outer_iter) {
    for(auto inner_iter=outer_iter->second.begin(); inner_iter!=outer_iter->second.end(); ++inner_iter) {
        std::cout << inner_iter->second << std::endl;
    }
}
    
做这样的事情:
typedef std::map<std::string, std::string> InnerMap;
typedef std::map<std::string, InnerMap> OuterMap;

Outermap mm;

...//set the initial values

for (OuterMap::iterator i = mm.begin(); i != mm.end(); ++i) {
    InnerMap &im = i->second;
    for (InnerMap::iterator ii = im.begin(); ii != im.end(); ++ii) {
        std::cout << "map[" 
                  << i->first 
                  << "][" 
                  << ii->first 
                  << "] =" 
                  << ii->second 
                  << 'n';
    }
}   
    
在C ++ 17中,您将能够使用“结构化绑定”功能,该功能允许您使用单个元组/对来定义具有不同名称的多个变量。例:
for (const auto& [name, description] : planet_descriptions) {
    std::cout << "Planet " << name << ":n" << description << "nn";
}
最初的提案(由杰出人物Bjarne Stroustrup,Herb Sutter和Gabriel Dos Reis提供)很有趣(建议的语法更直观恕我直言);这个标准的建议措辞也很难阅读,但更接近实际的内容。     
C ++ 11:
std::map< std::string, std::map<std::string, std::string> > m;
m["name1"]["value1"] = "data1";
m["name1"]["value2"] = "data2";
m["name2"]["value1"] = "data1";
m["name2"]["value2"] = "data2";
m["name3"]["value1"] = "data1";
m["name3"]["value2"] = "data2";

for (auto i : m)
    for (auto j : i.second)
        cout << i.first.c_str() << ":" << j.first.c_str() << ":" << j.second.c_str() << endl;
输出:
name1:value1:data1
name1:value2:data2
name2:value1:data1
name2:value2:data2
name3:value1:data1
name3:value2:data2
    
当map为const时使用
std::map< std::string, std::map<std::string, std::string> >::const_iterator
。     
正如einpoklum在他们的回答中提到的,从C ++ 17开始,你也可以使用结构化绑定声明。我想通过提供一个完整的解决方案,以舒适的方式迭代地图地图来扩展它:
int main() {
    std::map<std::string, std::map<std::string, std::string>> m {
        {"name1", {{"value1", "data1"}, {"value2", "data2"}}},
        {"name2", {{"value1", "data1"}, {"value2", "data2"}}},
        {"name3", {{"value1", "data1"}, {"value2", "data2"}}}
    };

    for (const auto& [k1, v1] : m)
        for (const auto& [k2, v2] : v1)
            std::cout << "m[" << k1 << "][" << k2 << "]=" << v2 << std::endl;

    return 0;
}
注1:为了填充地图,我使用了初始化列表(这是一个C ++ 11特性)。这有时可以方便地保持固定的初始化紧凑。 注意2:如果要在循环中修改地图
m
,则必须删除
const
关键字。 Coliru代码     

要回复问题请先登录注册