stl :: multimap – 我如何获得数据组?
Multimap本质上具有按键sorting的数据组。 我想要一个方法,我可以访问这些个人群体,并获得他们的总值。 例如,在一个std::multimap< string, int >
我的商店
{"Group1", 1}, {"Group1", 2}, {"Group1", 3}, {"Group2", 10}, {"Group2", 11}, {"Group2", 12}
已经存储这些值,我应该能够迭代这个多图,并获得每个“组”的聚合值。 问题是在STL中没有定义任何以这种方式访问MultiMaps的函数。 我可以使用lower_bound
, upper_bound
手动迭代multimap和总计组的内容,但我希望能有更好的方法已经在STL中定义? 任何人都可以提出一个解决scheme,我怎样才能得到上面的例子中的一个组的聚合值。
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>());
// 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
如果你已经知道键,你可以使用multimap::equal_range
来获取迭代器到组的开始和结束; 使用任何标准algorithm从范围中获得所需的结果。 如果你不知道密钥,你可以从begin()
开始,自己遍历它们,比较键来find每个新组的开始。
您可以使用可以包含每个组的总和的备用容器。 要做到这一点,你可能会做这样的事情:
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; } );
不是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"; } } }
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.