stl :: multimap: come ottengo gruppi di dati?

In sostanza, Multimap ha gruppi di dati ordinati per chiave. Voglio un metodo con cui potrei accedere a questi singoli gruppi e ottenere i loro valori aggregati. Ad esempio, in un file std::multimap I

 {"Group1", 1}, {"Group1", 2}, {"Group1", 3}, {"Group2", 10}, {"Group2", 11}, {"Group2", 12} 

Dopo aver memorizzato questi valori, dovrei essere in grado di iterare questa multimap e ottenere i valori aggregati di ciascun “gruppo”. Il problema è che non ci sono funzioni definite in STL per accedere a MultiMaps in questo modo. Potrei usare lower_bound , upper_bound per iterare manualmente la lower_bound e upper_bound i contenuti del gruppo, ma spero che ci possano essere modi migliori già definiti in STL? Qualcuno può proporre una soluzione su come ottenere i valori aggregati per un gruppo nell’esempio sopra.

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

È a senso unico

Modificare:

Se non conosci il gruppo che stai cercando e stai visitando ogni gruppo, è ansible ottenere il range del gruppo successivo in questo modo:

 template  struct Less : public std::binary_function { 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()); 
 // samekey.cpp -- Process groups with identical keys in a multimap #include  #include  #include  using namespace std; typedef multimap 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 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 

Se conosci già le chiavi, puoi usare multimap::equal_range per ottenere gli iteratori all’inizio e alla fine del gruppo; utilizzare qualsiasi algoritmo standard per ottenere i risultati desiderati dalla gamma. Se non conosci i tasti, puoi iniziare da begin() e scorrere da solo te stesso, confrontando le chiavi per trovare l’inizio di ogni nuovo gruppo.

È ansible utilizzare un contenitore alternativo che può contenere le somme aggregate di ciascun gruppo. Per fare questo potresti fare qualcosa come:

 template  struct group_add { typedef map 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  group_add make_group_adder(map & map_) { return group_add(map_); }; // ... multimap members; // populate members map group_aggregates; for_each(members.begin(), members.end(), make_group_adder(group_aggregates)); // group_aggregates now has the sums per group 

Certo, se hai Lambda (in C ++ 0x) potrebbe essere più semplice:

 multimap members; map group_aggregates; for_each(members.begin(), members.end(), [&group_aggregates](multimap::value_type const & element) { group_aggregates[element.first] += element.second; } ); 
 equal_range Syntax: #include  pair 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. 

Non una risposta multimap, ma puoi fare cose come le seguenti, se lo desideri.

 #include  #include  #include  #include  #include  #include  using namespace std; using namespace boost; using namespace boost::assign; int main() { typedef map > 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"; } } }