example c++ stl multimap

c++ - example - multimap insert



stl:: multimap: ¿cómo obtengo grupos de datos? (6)

Multimap esencialmente tiene grupos de datos ordenados por la clave. Quiero un método por el que pueda acceder a estos grupos individuales y obtener sus valores agregados. Por ejemplo, en una tienda std::multimap< string, int > I store

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

Habiendo almacenado estos valores, debería ser capaz de iterar este multimapa y obtener los valores agregados de cada "grupo". El problema es que no hay funciones definidas en STL para acceder a MultiMaps de tal manera. Podría usar lower_bound , upper_bound para iterar manualmente el multimap y sumar los contenidos del grupo, pero espero que haya mejores formas ya definidas en STL. ¿Alguien puede proponer una solución sobre cómo podría obtener los valores agregados para un grupo en el ejemplo anterior?


No es una respuesta multimapa, pero puede hacer las siguientes cosas si así lo desea.

#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"; } } }


Puede usar un contenedor alternativo que puede contener las sumas agregadas de cada grupo. Para hacer esto, puede hacer algo como:

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

Por supuesto, si tiene Lambda (en C ++ 0x) podría ser más 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; } );


Si ya conoce las claves, puede usar multimap::equal_range para obtener los iteradores al principio y al final del grupo; use cualquier algoritmo estándar para obtener los resultados deseados del rango. Si no conoce las claves, puede comenzar desde el begin() e iterar por ellas, comparando las claves para encontrar el inicio de cada grupo nuevo.


// 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


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.


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

Es de una manera.

Editar:

Si no conoce el grupo que está buscando y solo está examinando cada grupo, puede obtener el rango del siguiente grupo de la siguiente manera:

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>());