Pregunta

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

{"Group1", 1}, 
{"Group1", 2}, 
{"Group1", 3}, 

{"Group2", 10}, 
{"Group2", 11}, 
{"Group2", 12}

Una vez almacenados estos valores, debería poder iterar este mapa múltiple y obtener los valores agregados de cada " group " ;. El problema es que no hay funciones definidas en STL para acceder a MultiMaps de esa manera. Podría usar lower_bound, upper_bound para iterar manualmente el mapa múltiple y totalizar el contenido 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.

¿Fue útil?

Solución

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

Es unidireccional.

Edición :

Si no conoce el grupo que está buscando y solo está revisando 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>());

Otros consejos

// 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 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 en begin() e iterarlas usted mismo, comparando las claves para encontrar el inicio de cada nuevo grupo.

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;
  }
  );
equal_range

Sintaxis:

#include <map>
pair<iterator, iterator> equal_range( const key_type& key );

La función equal_range() devuelve dos iteradores: uno para el primer elemento que contiene clave, otro para un punto justo después del último elemento que contiene clave.

No es una respuesta multimap, pero puede hacer cosas como las siguientes 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";
        }
    }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top