1

Please help!. How to sum up all the elements in a multimap in c++ having the same key. I have the follwing multimap:

multimap <string,int> mymap;

and I want to sum all values for a particular string. Any approach would be appreciated.

ks1322
  • 33,961
  • 14
  • 109
  • 164
Dref D
  • 257
  • 2
  • 17

2 Answers2

3

Something like this may work for you:

#include <string>
#include <map>
#include <numeric>
#include <functional>
#include <iostream>

struct plus2nd {
    template <typename T1, typename T2>
    inline T1 operator()(T1 t1, const T2 &t2) const {
        return t1 + t2.second;
    }
};

template <typename Map, typename Key, typename Value>
Value accumulate_range(const Map & map, const Key & key, Value init)
{
    typedef typename Map::const_iterator const_iterator;
    typedef typename Map::value_type value_type;
    std::pair<const_iterator, const_iterator> range = map.equal_range(key);
    return std::accumulate(range.first, range.second, init, plus2nd());
}

int main()
{
    std::multimap<std::string, int> mymap;
    mymap.insert(std::multimap<std::string, int>::value_type("A", 1));
    mymap.insert(std::multimap<std::string, int>::value_type("B", 3));
    mymap.insert(std::multimap<std::string, int>::value_type("A", 4));
    mymap.insert(std::multimap<std::string, int>::value_type("B", 4));
    std::cout << "Sum of A: " << accumulate_range(mymap, "A", 0) << std::endl;
    std::cout << "Sum of B: " << accumulate_range(mymap, "B", 0) << std::endl;
}

See also:

Community
  • 1
  • 1
0

your accumulate function wont work that way because your map provides iterators with first and second and you only want to sum up it->second. You will have to write your own sum-function and pass it to accumlute. There already is a topic that describes this, please see multimap accumulate values for the answer of Matthieu M.

edit: The following should solve your problem.

int map_acc(int lhs, const std::pair<std::string, int> & rhs)
{
  return lhs + rhs.second;
}

std::pair<std::multimap<std::string,int>::const_iterator, std::multimap<std::string,int>::const_iterator> range = mymap.equal_range("somekey");
int result = std::accumulate(range.first, range.second, 0, &map_acc);

edit 2: If you want a more generic approach, go for Vlad Lazarenko answer. But considering your question, this might be overkill.

Community
  • 1
  • 1
Betagan
  • 121
  • 3
  • This should have been a comment to my answer I guess. I will remove it as it is obviously wrong. Thank you - I had no time to try that out. – Ivaylo Strandjev Jan 03 '13 at 15:15
  • but it say buf_map has not been declared!! – Dref D Jan 03 '13 at 15:19
  • the range from it->first to it->second is correct. all algorithm using stl range iterator pairs follow the convention [first, last) –  Jan 03 '13 at 15:20
  • you have to replace buf_map with the name of your map variable. The answer I linked uses the names relevant to that question :) – Betagan Jan 03 '13 at 15:21
  • @arrows `accumulate(range.first, range.second, 0);` will try to sum up (*it) while the TO wants to sum up (*it)->second. accumulate just does not work on multimaps out-of-the-box as it can not know what you want to sum up. – Betagan Jan 03 '13 at 15:24