C++ stl::multimap - 如何获取数据组?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/247818/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
stl::multimap - how do i get groups of data?
提问by the_Saint
Multimap essentially has groups of data sorted by the key. I want a method by which I could access these individual groups and get their aggregate values.
For example, in a std::multimap< string, int >
I store
Multimap 本质上具有按键排序的数据组。我想要一种方法,通过它我可以访问这些单独的组并获取它们的聚合值。例如,在std::multimap< string, int >
I 商店中
{"Group1", 1},
{"Group1", 2},
{"Group1", 3},
{"Group2", 10},
{"Group2", 11},
{"Group2", 12}
Having stored these values, I should be able to iterate this multimap and get the aggregate values of each "group". Problem is there aren't any functions defined in STL to access MultiMaps in such a way. I could use lower_bound
, upper_bound
to manually iterate the multimap and total the group's contents, but I am hoping there could be better ways already defined in STL ? Can anyone propose a solution as to how I could get the aggregate values for a group in the above example.
存储这些值后,我应该能够迭代这个多重映射并获得每个“组”的聚合值。问题是 STL 中没有定义任何函数来以这种方式访问 MultiMap。我可以使用lower_bound
,upper_bound
手动迭代 multimap 并汇总组的内容,但我希望 STL 中已经定义了更好的方法?任何人都可以提出一个解决方案,说明我如何在上面的例子中获得一个组的聚合值。
回答by Greg Rogers
pair<Iter, Iter> range = my_multimap.equal_range("Group1");
int total = accumulate(range.first, range.second, 0);
Is one way.
是一种方式。
Edit:
编辑:
If you don't know the group you are looking for, and are just going through each group, getting the next group's range can be done like so:
如果您不知道要查找的组,而只是浏览每个组,则可以像这样获取下一组的范围:
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>());
回答by the_Saint
// 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
回答by Mark Ransom
If you already know the keys, you can use multimap::equal_range
to get the iterators to the beginning and end of the group; use any standard algorithm to get the desired results from the range. If you don't know the keys, you can start at begin()
and iterate through them yourself, comparing keys to find the start of each new group.
如果您已经知道密钥,您可以使用multimap::equal_range
获取迭代器到组的开头和结尾;使用任何标准算法从范围中获得所需的结果。如果您不知道键,您可以从 at 开始begin()
并自己遍历它们,比较键以找到每个新组的开始。
回答by Dean Michael
You can use an alternate container that can contain the aggregate sums of each group. To do this you might do something like:
您可以使用可以包含每个组的总和的备用容器。为此,您可以执行以下操作:
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
Of course, if you have Lambda's (in C++0x) it could be simpler:
当然,如果您有 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;
}
);
回答by Hayek.Yu
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.
该函数equal_range()
返回两个迭代器 - 一个指向包含键的第一个元素,另一个指向包含键的最后一个元素之后的点。
回答by Shadow2531
Not a multimap answer, but you can do things like the following if you so choose.
不是多图答案,但如果您愿意,您可以执行以下操作。
#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";
}
}
}