如何在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";
我如何通过这个映射循环并访问各种值?
第一个解决方案是使用range_based for循环,像这样:
注意:当range_expression的类型是std::map时,则range_declaration的类型是std::pair。
for ( range_declaration : range_expression )
//loop_statement
代码1:
typedef std::map<std::string, std::map<std::string, std::string>> StringToStringMap;
StringToStringMap my_map;
for(const auto &pair1 : my_map)
{
// Type of pair1 is std::pair<std::string, std::map<std::string, std::string>>
// pair1.first point to std::string (first key)
// pair1.second point to std::map<std::string, std::string> (inner map)
for(const auto &pair2 : pair1.second)
{
// pair2.first is the second(inner) key
// pair2.second is the value
}
}
第二个解决方案:
代码2
typedef std::map<std::string, std::string> StringMap;
typedef std::map<std::string, StringMap> StringToStringMap;
StringToStringMap my_map;
for(StringToStringMap::iterator it1 = my_map.begin(); it1 != my_map.end(); it1++)
{
// it1->first point to first key
// it2->second point to inner map
for(StringMap::iterator it2 = it1->second.begin(); it2 != it1->second.end(); it2++)
{
// it2->second point to value
// it2->first point to second(inner) key
}
}
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;
}
}
第一个解决方案是使用range_based for循环,像这样:
注意:当range_expression的类型是std::map时,则range_declaration的类型是std::pair。
for ( range_declaration : range_expression )
//loop_statement
代码1:
typedef std::map<std::string, std::map<std::string, std::string>> StringToStringMap;
StringToStringMap my_map;
for(const auto &pair1 : my_map)
{
// Type of pair1 is std::pair<std::string, std::map<std::string, std::string>>
// pair1.first point to std::string (first key)
// pair1.second point to std::map<std::string, std::string> (inner map)
for(const auto &pair2 : pair1.second)
{
// pair2.first is the second(inner) key
// pair2.second is the value
}
}
第二个解决方案:
代码2
typedef std::map<std::string, std::string> StringMap;
typedef std::map<std::string, StringMap> StringToStringMap;
StringToStringMap my_map;
for(StringToStringMap::iterator it1 = my_map.begin(); it1 != my_map.end(); it1++)
{
// it1->first point to first key
// it2->second point to inner map
for(StringMap::iterator it2 = it1->second.begin(); it2 != it1->second.end(); it2++)
{
// it2->second point to value
// it2->first point to second(inner) key
}
}
正如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;
}
输出:
m [name1] [value1] = data1
m [name1] [value2] =身份不明
m [name2] [value1] = data1
m [name2] [value2] =身份不明
m [name3] [value1] = data1
m [name3] [value2] =身份不明
注1:为了填充映射,我使用了初始化列表(这是c++ 11的特性)。这有时可以方便地保持固定的初始化紧凑。
注2:如果你想在循环中修改映射m,你必须删除const关键字。
Coliru上的代码