STL :: Multimap- 데이터 그룹을 어떻게 얻습니까?
문제
MultiMap에는 기본적으로 키에 의해 정렬 된 데이터 그룹이 있습니다. 나는이 개별 그룹에 액세스하고 그들의 집계 값을 얻을 수있는 방법을 원합니다. 예를 들어, a std::multimap< string, int >
나는 보관한다
{"Group1", 1},
{"Group1", 2},
{"Group1", 3},
{"Group2", 10},
{"Group2", 11},
{"Group2", 12}
이 값을 저장 한 후, 나는이 멀티 맵을 반복하고 각 "그룹"의 집계 값을 얻을 수 있어야합니다. 문제는 STL에서 멀티 맵에 액세스하기 위해 정의 된 기능이 없다는 것입니다. 나는 사용할 수있다 lower_bound
, upper_bound
멀티 맵과 그룹의 내용을 수동으로 반복하려면 STL에서 이미 정의 된 더 나은 방법이있을 수 있기를 바랍니다. 위의 예에서 그룹의 집계 값을 어떻게 얻을 수 있는지에 대한 솔루션을 제안 할 수 있습니까?
해결책
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
반복자를 그룹의 시작과 끝으로 가져 오기 위해; 표준 알고리즘을 사용하여 원하는 결과를 얻으십시오. 열쇠를 모른다면 시작할 수 있습니다. begin()
그리고 각각의 새로운 그룹의 시작을 찾기 위해 열쇠를 비교하여 그들 자신을 통해 반복하십시오.
각 그룹의 집계 합을 포함 할 수있는 대체 컨테이너를 사용할 수 있습니다. 이렇게하려면 다음과 같은 작업을 수행 할 수 있습니다.
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;
}
);
equal_range
통사론:
#include <map>
pair<iterator, iterator> equal_range( const key_type& key );
함수 equal_range()
두 개의 반복자를 반환합니다. 하나는 키를 포함하는 첫 번째 요소로, 다른 하나는 키를 포함하는 마지막 요소 직후에 포인트로 반환합니다.
멀티 맵 답변은 아니지만 선택하면 다음과 같은 작업을 수행 할 수 있습니다.
#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";
}
}
}