C++Map :Accessing map inside a map

281 Views Asked by At

How can I loop, access and assign through a std::map in C++? My map is defined as:

std::map<std::string, std::map<std::string, int>>

For example, the above container holds data like this:

m["country"]["capital"] = value;
m["country1"]["capital1"] = value;
m["country2"]["capital2"] = value;

based on the country and capital,weather value gets updated

at present if and map is used

map<string,int>mp;                                                                                              
if(Albania)
map[Tirana]= weathervalue;
if("Algeria")
map["Algiers"] = weathervalue;

Any hints,indication and ideas to optimise is always welcome

2

There are 2 best solutions below

11
On
for(auto& it:mp){
   for(auto& it1: it.second){
        it1.second=weathervalue;
}

You can add conditions to this loops but this is the basic way of traversing map inside a map.

Basically map is a structure of key-value pairs so when traversing it you treat it as such. Nested map is the value part of the key-value pair of the original map and as such it is accessed as (name_of_iterator). second.

As m88 suggested: Adds to clarity of the code

  for(auto& [country,submap]:mp){
     for(auto& [capital,wetherValue]: submap){
          wetherValue=New_Weather_Value;
  }

Which is the feature of structured bindings added in C++17 standard.

Answer to the additional question.

  typedef map<string,int> mp; 
//note that you gave the alias mp to the map so you can not use it as as variable name
    void function(){
          int new_value=50; // some value
          mp::iterator inner; // iterator of inner map
          map<int,mp> mymap; // main map
          map<int,mp>::iterator outer; // iterator of the main map
          for (outer=mymap.begin();outer!=mymap.end();outer++){
            for(inner=outer->second.begin();inner!=outer->second.end();inner++)
               inner->second= new_value;
              //do some other stuff
           }
    
    }
//Additionally note that you must use the smart pointer in the case of nested maps

This is the one way but you can also use first two code snippets (since keyword auto detects the type of variable in use).

5
On

you can traverse like this

   std::map< std::string, std::map<std::string, int> > myMap;
    
    for(auto& iter : myMap)
    {
        for(auto& childIter : iter.second)
        {
            // do here what you want i.e
            if(childIter.first == "xyz")
            childIter.second = 20;
        }
    }
// OR
    for(auto& [country, map] : myMap)
    {
      for(auto& [capital , weather] : map)
      {
        if(capital == "xyz")
          weather = 20;
      }
    }

another way

 typedef map<string,int> innermap;
 std::map< std::string, innermap > myMap;

 for(auto iterOuter = myMap.begin(); iterOuter != myMap.end(); iterOuter++)
    {
        for(map<string, int>::iterator iterInner = iterOuter->second.begin(); iterInner  != iterOuter->second.end(); iterInner++)
        {
            // do here what you want
        }
    }