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

Jac*_*ack 287 c++ iteration dictionary loops idioms

如何std::map在C++中循环?我的地图定义为:

std::map< std::string, std::map<std::string, std::string> >
Run Code Online (Sandbox Code Playgroud)

例如,上面的容器包含如下数据:

m["name1"]["value1"] = "data1";
m["name1"]["value2"] = "data2";
m["name2"]["value1"] = "data1";
m["name2"]["value2"] = "data2";
m["name3"]["value1"] = "data1";
m["name3"]["value2"] = "data2";
Run Code Online (Sandbox Code Playgroud)

如何遍历此地图并访问各种值?

Rio*_*iot 558

旧的问题,但剩下的答案已经过时了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
  }
}
Run Code Online (Sandbox Code Playgroud)

这应该比早期版本更清晰,并避免不必要的副本.

有人赞成用引用变量的明确定义替换注释(如果未使用则会被优化掉):

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;
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 保持答案相关的道具 - 我只希望这可以越来越接近顶部.将这个编辑到接受的答案中可能是合适的吗?(这是我们在TeX.SX上所做的,但SO是一种不同的文化.) (13认同)
  • 在指定类型之前或之后的@Parham const是一个偏好的问题,但我选择将它保持在右边,因为它使得在使用指针的情况下更清楚; 例如,当同时使用```int const*x```和```int*const x```时,你可以将它写成```int const*const x```,这比IM`更清晰IMO `const int*const x```.但它只是从左到右解析,所以效果是一样的.请参阅此问题的答案:http://stackoverflow.com/questions/5503352/const-before-or-const-after (6认同)
  • @TannerSummers因为按值访问会增加复制每个元素的低效率; 另外,如果你想修改内容,你需要通过引用(或指针)而不是值来访问元素. (5认同)
  • 只是一个简单的问题,你在'auto`之后编写`const`的决定是否有任何相关性?这纯粹是美学吗? (2认同)
  • auto const&ent2中的&含义是什么? (2认同)
  • @ davidhood2传递任何没有&为参考或*为指针的东西正在复制,是的. (2认同)

Pup*_*ppy 308

您可以使用迭代器.

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.
}
Run Code Online (Sandbox Code Playgroud)

  • 对于c ++ 11来说,这已经过时了.只是用于(auto iter:mymap) (127认同)
  • 对于c ++ 11,您应该使用(auto&iter:mymap)来避免潜在的副本. (37认同)
  • 执行++迭代器比使用迭代器++更有效,因为它在递增时避免了不必要的复制. (28认同)
  • 使用auto大大简化了C++ 11的循环:`for(auto iterator = m.begin(); iterator!= m.end(); iterator ++)` (19认同)
  • 除非他打算修改地图,否则使用const_iterator会更好. (10认同)
  • @ user11177:如果你这样做,你得到一对,而不是迭代器,所以它应该是`for(auto&entry:mymap)` (3认同)
  • 这是因为it_type是类型,而`iterator`是变量.我的错. (2认同)
  • @quant _maybe_,但是为什么在完全没必要和语义光栅时冒险?事实上,几乎每个人似乎都默认延迟增量/减量是一种可怕的习惯,这是毫无意义的,除非事先需要临时性的东西.我认为这种普遍趋势的责任在于调用语言C++而不是++ C的可怕决定 - 好像C已经变好了,但更好的版本被丢弃了,我们得到了原版的副本,嘿嘿. (2认同)

Axe*_*ing 59

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

或者在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;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 甚至更简单:for(const auto&element:map)cout << element.second; (13认同)
  • 您应该使用auto&,或者如果您不修改地图,甚至是const auto&.另外,更喜欢非成员begin()和end(),即(const auto&iter = begin(map); ...). (2认同)

小智 24

做这样的事情:

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';
    }
}   
Run Code Online (Sandbox Code Playgroud)


ein*_*ica 24

在C++ 17中,您将能够使用"结构化绑定"功能,该功能允许您使用单个元组/对来定义具有不同名称的多个变量.例:

for (const auto& [name, description] : planet_descriptions) {
    std::cout << "Planet " << name << ":\n" << description << "\n\n";
}
Run Code Online (Sandbox Code Playgroud)

原来的建议(由灯具Bjarne的Stroustrup的,香草萨特和Gabriel杜斯雷斯)是有趣的阅读(和建议的语法更直观恕我直言); 这个标准建议措辞也很难阅读,但更接近实际的内容.

  • 这是非常漂亮的我需要投票,尽管C++ 17还没有"存在".男人,他们通过更容易编写干净和安全的代码来真正重振C++. (2认同)

use*_*233 12

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;
Run Code Online (Sandbox Code Playgroud)

输出:

name1:value1:data1
name1:value2:data2
name2:value1:data1
name2:value2:data2
name3:value1:data1
name3:value2:data2
Run Code Online (Sandbox Code Playgroud)

  • 这个答案与http://stackoverflow.com/a/27344958/3658660有何不同?除了它到处都在复制。 (2认同)