C++ 如何在 STL 映射中迭代 STL 映射?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4516495/
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 iterate over an STL map inside an STL map?
提问by Prasanth Madhavan
I have an STL map definition as follows:
我有一个 STL 映射定义如下:
map<string, map<int, string> > info;
I iterate that map using the following code:
我使用以下代码迭代该地图:
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;
}
}
Is this the correct way to iterate or is there a better way to do so? The above code works for me, but I'm looking for a more elegant solution.
这是迭代的正确方法还是有更好的方法?上面的代码对我有用,但我正在寻找更优雅的解决方案。
回答by icecrime
This is correct, it just lacks a few typedef
and readability improvements :
这是正确的,它只是缺乏一些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)
{
/* ... */
}
}
回答by Juraj Blaho
If C++11 is available you may use range for
loop:
如果 C++11 可用,您可以使用范围for
循环:
for(auto &i: info) {
for(auto &j: i.second) {
/* */
}
}
If only C++11 auto
is available:
如果只有 C++11auto
可用:
for( auto i=info.begin(); i!=info.end(); ++i) {
for( auto j=i->second.begin(); j!=i->second.end(); ++j) {
/* */
}
}
If you may use BOOST there is BOOST_FOREACH:
如果您可以使用 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 */
}
}
回答by Santosh Chauhan
If c++11 is available, we could use stl algorithm for_each and lambda functions to get a elegant solution
如果 c++11 可用,我们可以使用 stl 算法 for_each 和 lambda 函数来获得优雅的解决方案
typedef map<int, string> INNERMAP;
typedef map<string, INNERMAP> OUTERMAP;
OUTERMAP theMapObject;
// populate the map object
// iterate the map object now
// 现在迭代地图对象
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
});
});
回答by Jaywalker
While it's not clear what problem you are solving by having a map inside a map, I don't think there is a better way of iterating on all the items without using these iterators. The only thing you can do to improve code readability is to use typedefs on the template types.
虽然不清楚在地图中放置地图要解决什么问题,但我认为没有更好的方法可以在不使用这些迭代器的情况下迭代所有项目。提高代码可读性的唯一方法是在模板类型上使用 typedef。
However, won't it be a better idea to define your map
as
但是,将您定义map
为
multimap <string, MyClass>
multimap <string, MyClass>
where MyClass
is defined as a pair of integer and a string, as well as a toString() method to dump the contents, etc?
whereMyClass
被定义为一对整数和一个字符串,以及一个 toString() 方法来转储内容等?
回答by B?ови?
If you want to iterate through both maps, then the way you presented is the best way. Now, if there is something specific you want to do then you might be better with using a function from the algorithm header.
如果您想遍历两个地图,那么您呈现的方式是最好的方式。现在,如果您想要做一些特定的事情,那么使用算法标题中的函数可能会更好。
回答by honk
If you have access to C++11features, then range-based for loopsas proposed in Juraj Blaho's answerseem to be the most readable option to me. However, if C++17is available to you, then you can use structured bindingstogether with those loops to further increase readability, as you can get rid of all first
and second
members:
如果您可以访问C++11功能,那么Juraj Blaho 的答案中提出的基于范围的 for 循环对我来说似乎是最易读的选项。但是,如果您可以使用C++17,那么您可以将结构化绑定与这些循环一起使用以进一步提高可读性,因为您可以摆脱 all和members:first
second
std::map<std::string, std::map<int, std::string>> info;
for (const auto &[k1, v1] : info) {
for (const auto &[k2, v2] : v1) {
std::cout << k1 << " : " << k2 << " : " << v2 << std::endl;
}
}