2008-10-29 75 views
31

Multimap基本上有按鍵排序的數據組。我想要一種方法,我可以訪問這些單個組並獲得它們的聚合值。 例如,在一個std::multimap< string, int >我存儲stl :: multimap - 我如何獲得數據組?

{"Group1", 1}, 
{"Group1", 2}, 
{"Group1", 3}, 

{"Group2", 10}, 
{"Group2", 11}, 
{"Group2", 12} 

具有存儲這些值,我應該能夠重複這種多重映射,並得到每一個「組」的合計值。問題是在STL中沒有定義以這種方式訪問​​MultiMaps的任何函數。我可以使用lower_bound,upper_bound來手動迭代multimap並總計組的內容,但我希望能在STL中定義更好的方法嗎?任何人都可以提出一個解決方案,以瞭解如何在上面的示例中獲得組的聚合值。

+0

非常優雅和這裏描述的lambda方法: http://stackoverflow.com/a/37680747/5516759 – 2016-06-07 13:29:40

回答

38
pair<Iter, Iter> range = my_multimap.equal_range("Group1"); 
int total = accumulate(range.first, range.second, 0); 

是一種方式。

編輯:

如果你不知道你正在尋找的組,只是要通過每個組,獲得下組的範圍可以像這樣做:

template <typename Pair> 
struct Less : public std::binary_function<Pair, Pair, bool> 
{ 
    bool operator()(const Pair &x, const Pair &y) const 
    { 
     return x.first < y.first; 
    } 
}; 

Iter first = mmap.begin(); 
Iter last = adjacent_find(first, mmap.end(), Less<MultimapType::value_type>()); 
+0

不應該是`x.first == y.first;`?你爲什麼使用`operator <`?根據`adjacent_find`的[document](http://www.cplusplus.com/reference/algorithm/adjacent_find/),謂詞參數應該返回比較結果與真(非零),這意味着它們是被認爲是相等的,並且假(零)不相等。爲什麼你返回不相等的結果是真的? – Meysam 2012-11-12 07:40:11

+2

是的,這似乎是一個錯誤。 `adjacent_find`需要一個「相等」的謂詞。另外,我確定有`std :: equal_to `準備好使用。 – leemes 2013-01-03 15:08:59

10

如果您已經知道密鑰,則可以使用multimap::equal_range將迭代器獲取到組的開始和結束位置;使用任何標準算法從範圍中獲得所需的結果。如果您不知道密鑰,您可以從begin()開始,並自己遍歷它們,比較密鑰以查找每個新組的開始。

-1

不是multimap答案,但如果您願意,可以按照以下方式進行操作。

#include <iostream> 
#include <vector> 
#include <map> 
#include <string> 
#include <boost/assign/list_of.hpp> 
#include <boost/foreach.hpp> 
using namespace std; 
using namespace boost; 
using namespace boost::assign; 

int main() { 
    typedef map<string, vector<int> > collection; 
    collection m; 
    m["Group 1"] = list_of(1)(2)(3); 
    m["Group 2"] = list_of(10)(11)(12); 
    collection::iterator g2 = m.find("Group 2"); 
    if (g2 != m.end()) { 
     BOOST_FOREACH(int& i, g2->second) { 
      cout << i << "\n"; 
     } 
    } 
} 
1

您可以使用可以包含每個組的總和的備用容器。要做到這一點,你可以這樣做:

template <class KeyType, class ValueType> 
struct group_add { 
    typedef map<KeyType, ValueType> map_type; 
    map_type & aggregates; 
    explicit group_add(map_type & aggregates_) 
    : aggregates(aggregates_) { }; 
    void operator() (map_type::value_type const & element) { 
    aggregates[element.first] += element.second; 
    }; 
}; 

template <class KeyType, class ValueType> 
group_add<KeyType, ValueType> 
make_group_adder(map<KeyType, ValueType> & map_) { 
    return group_add<KeyType, ValueType>(map_); 
}; 

// ... 
multimap<string, int> members; 
// populate members 
map<string, int> group_aggregates; 
for_each(members.begin(), members.end(), 
    make_group_adder(group_aggregates)); 
// group_aggregates now has the sums per group 

當然,如果你有LAMBDA的(C++ 0x中),也可以是簡單的:

multimap<string, int> members; 
map<string, int> group_aggregates; 
for_each(members.begin(), members.end(), 
    [&group_aggregates](multimap<string, int>::value_type const & element) { 
    group_aggregates[element.first] += element.second; 
    } 
); 
19
// samekey.cpp -- Process groups with identical keys in a multimap 

#include <iostream> 
#include <string> 
#include <map> 
using namespace std; 

typedef multimap<string, int> StringToIntMap; 
typedef StringToIntMap::iterator mapIter; 

int main() 
{ 
    StringToIntMap mymap; 

    mymap.insert(make_pair("Group2", 11)); 
    mymap.insert(make_pair("Group1", 3)); 
    mymap.insert(make_pair("Group2", 10)); 
    mymap.insert(make_pair("Group1", 1)); 
    mymap.insert(make_pair("Group2", 12)); 
    mymap.insert(make_pair("Group1", 2)); 

    cout << "mymap contains:" << endl; 

    mapIter m_it, s_it; 

    for (m_it = mymap.begin(); m_it != mymap.end(); m_it = s_it) 
    { 
     string theKey = (*m_it).first; 

     cout << endl; 
     cout << " key = '" << theKey << "'" << endl; 

     pair<mapIter, mapIter> keyRange = mymap.equal_range(theKey); 

     // Iterate over all map elements with key == theKey 

     for (s_it = keyRange.first; s_it != keyRange.second; ++s_it) 
     { 
      cout << " value = " << (*s_it).second << endl; 
     } 
    } 

    return 0; 

} // end main 

// end samekey.cpp 
0
equal_range 
Syntax:  
#include <map> 
pair<iterator, iterator> equal_range(const key_type& key); 
The function equal_range() returns two iterators - one to the first 
element that contains key, another to a point just after the last 
element that contains key.