I want to modify a place on std :: map, iterate over it

I need to know the best way to make a modification in place of the map without a local copy of the changed values, and then click it again on the original map.

I have described in detail this 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; } 
+4
source share
9 answers

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

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

for more complex modifications, you can take the value from the link:

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

In C ++, you usually cannot change the collection during iteration, but that means you cannot delete / add items. Changing existing elements is generally excellent in C ++ 11. What you cannot change is the key in map and any part of the element in set , but it is const in C ++ 11 anyway, so you cannot change. In C ++ 03, you need to remember that you do not need to change the key part of an element in set .

+5
source

Just take the link to the value.

 EmployeeDetail& det = iter->second; // notice new '&' character. det.salary = 1000; // modifies the 'EmployeeDetail' object in-place. 
+3
source

iter->second is a reference to the EmployeeDetail object, which you can change directly - for example,

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

No need for transformMap

+3
source

Will not just iterate over the map and do

iter-> second.salary = 1000;

solve your problem?

+1
source

Good to change the values ​​of map objects ( second part of value_type ) during foreach iteration. You simply cannot add or remove any keys - no insert or erase .

+1
source

Can you do the following?

 it->second.salary = 1000; 
+1
source

You cannot use std::transform because it assigns iterators, and the first element of the map iterator is always const.

Also, your code does not show us a comparison for your employee key, so I assume you have one that implements a strict weak order. The basic plan:

You can use for_each , though, since the predicate can be stateless:

 class SalaryUpdater { public: SalaryUpdater(const std::string& name, int age) : name_(name), age_(age) { } void operator()(EmployeeMap::value_type& item) { if(compareByNameAge(name_, age_, item.first)) { item.second.salary = 1000; } } private: std::string name_; int age_; }; int main() { EmployeeMap eMap; // insert entries to the map std::for_each(eMap.begin(), eMap.end(), SalaryUpdater("John", 10)); } 
+1
source

Get a link to EmployeeDetail.

0
source

If you have C ++ 11, try the following:

 for (auto& pair : eMap ) if (pair.first.name == "Rob") pair.second.salary *= 1000; 

Note. You can only change pair.second . pair.first is a constant and cannot be changed (this is the key to the map).

If you do not have C ++ 11, try the following:

 for(EmployeeMap::iterator it = eMap.begin(); it != eMap.end(); ++it) if(pair.first.name == "Rob") pair.second.hours /= 2; 
0
source

Source: https://habr.com/ru/post/1395429/


All Articles