1

I have a map in my program that stores the code of a Product p and the amount of it.

If a ask for a new request, and if the product already exists in the map, i just need to sum the second element of the pair(code, amount) to the element in the map.

How can I do this?

void Request :: addItem (Product p, double amount) {
    if(this->isItemRequest(p)) {
        //p already exists in the map.
    }

    this->rdata.insert(pair<int, double>((int)p.getCode(), amount));
}

Thanks a lot!

ddz
  • 526
  • 3
  • 15
  • I would normally remove the `this->`; it's always redundant and most often simply clutters the code (though there are rare cases in which it's use could be justified). – jia103 Feb 14 '14 at 15:17

4 Answers4

3

Assuming your map is declared within the Request class as std::map<int, double> rdata, the code can be:

void Request::addItem( Product p, double amount )
{
    if ( this->isItemRequest(p) )
    {
        int Code = int(p.getCode);
        this->rdata[ Code ] += amount;
    }

    this->rdata.insert( pair<int, double>(int(p.getCode), amount) );
}

However, if isItemRequest() is just a trivial check, your code can be simplified to just:

void Request::addItem( Product p, double amount )
{
    int Code = int(p.getCode);
    this->rdata[ Code ] += amount;
}

P.S. Maybe, it is a good idea (if you can change the interface) to pass Product by const reference.

Sergey K.
  • 24,894
  • 13
  • 106
  • 174
  • What if `rdata` previously had no entry for `Code` in the map? I don't believe it'll be default-initialized to 0.0. I think you still need the `rdata.insert()` or at least an initialization of `rdata[ Code ] = 0.0` somewhere. – jia103 Feb 14 '14 at 15:18
  • This mean that i can access an element of a map just using one of the pairs? Or it has to be the first one? – ddz Feb 14 '14 at 15:20
  • @jia103: this is perfectly valid. http://www.cplusplus.com/reference/map/map/operator[]/ – Sergey K. Feb 14 '14 at 15:20
  • 1
    @Luiz Eduardo F: there is only one pair in the map for each different code of the Product – Sergey K. Feb 14 '14 at 15:22
  • @SergeyK.: I agree it's perfectly valid; however, the second paragraph of your referenced link states, "the element is constructed using its default constructor". For doubles, floats, ints, and bools, a default-constructed instance is not initialized to zero. – jia103 Feb 14 '14 at 15:34
  • @jia103: ``std::map`` uses ``T()`` syntax to construct an object. ``double()`` is equal to casting ``0`` to a double and yields ``0.0``. Here you can find a more elaborate text: http://stackoverflow.com/a/4524064/1065190 – Sergey K. Feb 14 '14 at 15:37
  • 3
    @jia103: Indeed, the linked description is incomplete and misleading. The inserted value is value-initialised which, for numeric types, means it is initialised to zero. The default constructor is only used for class types with a user-declared default constructor. – Mike Seymour Feb 14 '14 at 15:42
2

If you call on:

this->rdata[key] = value;

you create a value using default constructor (int() initializes to 0), return reference to it, and call operator= on it. You can avoid that by checking if key exist first:

this->rdata.count(key) != 0

or simplier

this->rdata.count(key)

if it exists you can use operatror=, operator+= and so on on reference returned by operator[]:

if (this->rdata.count(key) == 0)
    this->rdata.insert( pair<int, double>( key, value ) );
else
    this->rdata[key] += value;

but in this simple case

this->rdata[key] += value;

should just do.

Mateusz Kubuszok
  • 24,995
  • 4
  • 42
  • 64
1

The simplest way to do that is

rdata[p.getCode()] += amount;

If it wasn't already in the map, then [] will insert an element with value zero, so the value will end up being amount. If it was, then amount is added to the existing value.

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
  • How do you know it'll always insert with value zero? Aren't doubles and ints normally uninitialized? – jia103 Feb 14 '14 at 15:19
  • 1
    @jia103: Because the standard specifies value-initialisation which, for numeric types, means zero-initialisation. – Mike Seymour Feb 14 '14 at 15:36
0

Easy: map.find :)

#include <iostream>
#include <map>
#include <string>

typedef std::map<std::string, int> StringIntMap;

int main() {
    StringIntMap map;
    map["coke"] = 10;
map["fries"] = 25;
    map["pizza"] = 50;
std::cout << "Before increase" << std::endl;
StringIntMap::const_iterator it;
for (it = map.begin(); it != map.end(); it++) {
    std::cout << it->first << ": " << it->second << std::endl;
}
std::cout << "Now, increase pizza +50" << std::endl;
StringIntMap::iterator item = map.find("pizza");
if (item != map.end()) {
    // pizza exists increase 50
    item->second += 50;
} else {
    std::cout << "Sorry, no pizza here" << std::endl;
}
std::cout << "after increase" << std::endl;
for (it = map.begin(); it != map.end(); it++) {
    std::cout << it->first << ": " << it->second << std::endl;
}
return 0;

}

Joel
  • 1,805
  • 1
  • 22
  • 22