Multimap a essentiellement des groupes de données triés par clé. Je veux une méthode par laquelle je pourrais accéder à ces groupes individuels et obtenir leurs valeurs agrégées. Par exemple, dans un std::multimap< string, int >
Je stocke
{"Group1", 1},
{"Group1", 2},
{"Group1", 3},
{"Group2", 10},
{"Group2", 11},
{"Group2", 12}
Après avoir stocké ces valeurs, je devrais être capable d'itérer cette carte multiple et d'obtenir les valeurs agrégées de chaque "groupe". Le problème est qu'aucune fonction n'est définie dans STL pour accéder à MultiMaps de cette manière. Je pourrais utiliser lower_bound
, upper_bound
pour itérer manuellement le multimap et additionner le contenu du groupe, mais j'espère qu'il pourrait y avoir de meilleures façons déjà définies en STL? Quelqu'un peut-il proposer une solution sur la façon dont je pourrais obtenir les valeurs agrégées pour un groupe dans l'exemple ci-dessus.
pair<Iter, Iter> range = my_multimap.equal_range("Group1");
int total = accumulate(range.first, range.second, 0);
Est une façon.
Modifier:
Si vous ne connaissez pas le groupe que vous recherchez et que vous parcourez simplement chaque groupe, obtenir la plage du groupe suivant peut se faire comme suit:
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
Si vous connaissez déjà les clés, vous pouvez utiliser multimap::equal_range
Pour amener les itérateurs au début et à la fin du groupe; utilisez n'importe quel algorithme standard pour obtenir les résultats souhaités de la plage. Si vous ne connaissez pas les clés, vous pouvez commencer à begin()
et les parcourir vous-même, en comparant les clés pour trouver le début de chaque nouveau groupe.
Vous pouvez utiliser un autre conteneur qui peut contenir les sommes agrégées de chaque groupe. Pour ce faire, vous pouvez faire quelque chose comme:
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
Bien sûr, si vous avez Lambda (en C++ 0x), cela pourrait être plus simple:
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
Syntaxe:
#include <map>
pair<iterator, iterator> equal_range( const key_type& key );
La fonction equal_range()
renvoie deux itérateurs - un pour le premier élément qui contient la clé, un autre pour un point juste après le dernier élément qui contient la clé.