如何循环遍历地图的 C++ 地图?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4844886/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I loop through a C++ map of maps?
提问by Hyman
How can I loop through a std::map
in C++? My map is defined as:
如何循环遍历std::map
C++ 中的 a?我的地图定义为:
std::map< std::string, std::map<std::string, std::string> >
For example, the above container holds data like this:
例如,上面的容器包含这样的数据:
m["name1"]["value1"] = "data1";
m["name1"]["value2"] = "data2";
m["name2"]["value1"] = "data1";
m["name2"]["value2"] = "data2";
m["name3"]["value1"] = "data1";
m["name3"]["value2"] = "data2";
How can I loop through this map and access the various values?
如何遍历此地图并访问各种值?
回答by Riot
Old question but the remaining answers are outdated as of C++11 - you can use a ranged based for loopand simply do:
老问题,但从 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
}
}
this should be much cleaner than the earlier versions, and avoids unnecessary copies.
这应该比早期版本更干净,并避免不必要的副本。
Some favour replacing the comments with explicit definitions of reference variables (which get optimised away if unused):
有些人赞成用引用变量的显式定义替换注释(如果未使用,则会被优化掉):
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;
}
}
回答by Puppy
You can use an iterator.
您可以使用迭代器。
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.
}
回答by Axel Gneiting
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;
}
}
or nicer in C++0x:
或者在 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;
}
}
回答by einpoklum
With C++17 (or later), you can use the "structured bindings" feature, which lets you define multiple variables, with different names, using a single tuple/pair. Example:
对于 C++17(或更高版本),您可以使用“结构化绑定”功能,该功能允许您使用单个元组/对定义具有不同名称的多个变量。例子:
for (const auto& [name, description] : planet_descriptions) {
std::cout << "Planet " << name << ":\n" << description << "\n\n";
}
The original proposal(by luminaries Bjarne Stroustrup, Herb Sutter and Gabriel Dos Reis) is fun to read (and the suggested syntax is more intuitive IMHO); there's also the proposed wording for the standardwhich is boring to read but is closer to what will actually go in.
在原来的建议(由灯具Bjarne的Stroustrup的,香草萨特和Gabriel杜斯雷斯)是有趣的阅读(和建议的语法更直观恕我直言); 还有为标准提出的措辞,读起来很无聊,但更接近实际的内容。
回答by einpoklum
Do something like this:
做这样的事情:
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';
}
}
回答by user1438233
C++11:
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;
output:
输出:
name1:value1:data1
name1:value2:data2
name2:value1:data1
name2:value2:data2
name3:value1:data1
name3:value2:data2
回答by Amir Saniyan
use std::map< std::string, std::map<std::string, std::string> >::const_iterator
when map is const.
std::map< std::string, std::map<std::string, std::string> >::const_iterator
当 map 为 const 时使用。
回答by honk
As einpoklummentioned in their answer, since C++17you can also use structured binding declarations. I want to extend on that by providing a full solution for iterating over a map of maps in a comfortable way:
正如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;
}
Note 1:For filling the map, I used an initializer list(which is a C++11feature). This can sometimes be handy to keep fixed initializations compact.
注 1:为了填充地图,我使用了一个初始化列表(这是一个C++11特性)。这有时可以方便地保持固定的初始化紧凑。
Note 2:If you want to modify the map m
within the loops, you have to remove the const
keywords.
注意2:如果要修改m
循环内的地图,则必须删除const
关键字。
回答by AmirSalar
First solution is Use range_based for loop, like:
第一个解决方案是使用 range_based for 循环,例如:
Note: When range_expression
's type is std::map
then a range_declaration
's type is std::pair
.
注意: Whenrange_expression
的类型是std::map
then arange_declaration
的类型是std::pair
。
for ( range_declaration : range_expression )
//loop_statement
Code 1:
代码 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
}
}
The Second Solution:
第二种解决方案:
Code 2
代码 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
}
}