Reputation: 91
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;
}
Upvotes: 9
Views: 11441
Reputation: 931
C++17 update with structured bindings:
for (auto &[key, detail] : employeeMap)
if (compareByNameAge(name, age, key))
detail.salary = 1000;
Upvotes: 0
Reputation: 96311
You can't use std::transform
because it assigns iterators, and the first
element of a map iterator is always const.
Additionally your code doesn't show us the comparison for your employee key, so I'll assume you have one that implements strict weak ordering. A basic outline:
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));
}
Upvotes: 1
Reputation: 168876
If you have C++11, try this:
for (auto& pair : eMap )
if (pair.first.name == "Rob")
pair.second.salary *= 1000;
Note: you can only change pair.second
. pair.first
is const, and must not be changed (it is, after all, the key to the map.)
If you don't have C++11, try this:
for(EmployeeMap::iterator it = eMap.begin(); it != eMap.end(); ++it)
if(pair.first.name == "Rob")
pair.second.hours /= 2;
Upvotes: 0
Reputation: 9354
Wouldn't just iterating over the map and doing
iter->second.salary = 1000;
solve your problem?
Upvotes: 1
Reputation: 20211
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
.
Upvotes: 9
Reputation: 16320
It's fine to alter the values of the map
objects (the second
part of the value_type
) during foreach
iteration. You just can't add or remove any keys--no insert
or erase
.
Upvotes: 1
Reputation: 33655
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
Upvotes: 6
Reputation: 45284
Just take a reference to the value.
EmployeeDetail& det = iter->second; // notice new '&' character.
det.salary = 1000; // modifies the 'EmployeeDetail' object in-place.
Upvotes: 4