Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

I want to perform in place modification to a std::map while iterating over it

Tags:

c++

I need to know the best way to do the in place modification to the map without taking a local copy of the values modified and then pushing it again into the original map.

I have detailed the snippet below that explains the problem:

#include <string>
#include <map>
struct EmployeeKey
{
    std::string name;
    int amount;
    int age;
};

struct EmployeeDetail
{
    std::string dept;
    int section;
    int salary;
};

bool compareByNameAge(const std::string& name,
                      const int& age,
                      const EmployeeKey& key )
{
    return name > key.name && age > key.age;
}

typedef std::map<EmployeeKey, EmployeeDetail> EmployeeMap;

int main()
{
    EmployeeMap eMap;
    // insert entries to the map
    int age = 10;
    std::string name = "John";

    EmployeeMap transformMap;
    foreach( iter, eMap )
    {
        if ( compareByNameAge(name, age, iter->first) )
        {
            //**This is what i want to avoid.......
            // take a copy of the data modified
            // push it in a new map.
            EmployeeDetail det = iter->second;
            det.salary = 1000;
            transformMap[iter->first] = det;
        }
    }

    //** Also, i need to avoid too...  
    // do the cpy of the modified values   
    // from the transform map to the   
    // original map  
    foreach( iter1, transformMap )  
        eMap[iter1->first] = iter1->second;
}  
like image 587
Sid Avatar asked Feb 08 '12 15:02

Sid


2 Answers

You can simply modifiy the element directly through the iterator (which points directly to the corresponding item):

foreach(iter, eMap)  
{  
   if (compareByNameAge(name, age, iter->first))  
     iter->second.salary = 1000;   
} 

for more complex modifications you could take the value by reference:

EmployeeDetail& det = iter->second;  
det.salary = 1000;  

In c++ you can typically not modify a collection while iterating, but that only means that you can't remove/add items. Modifying existing items is typically fine in C++11. What you can't modify is the key in a map and any part of the element in set, but those are const in c++11 anyways, so you can't modify those. In C++03 you need to remember not to change the keypart of an element in a set.

like image 146
Grizzly Avatar answered Oct 04 '22 22:10

Grizzly


iter->second is a reference to the EmployeeDetail object, which you can modify directly - e.g.

   foreach( iter, eMap )  
   {  
       if ( compareByNameAge(name, age, iter->first) )  
       {
           iter->second.salary = 1000;
       }  
   }  

No need for the transformMap

like image 32
Nim Avatar answered Oct 05 '22 00:10

Nim