stl:: multimap - jak uzyskać grupy danych?

Multimap zasadniczo zawiera grupy danych posortowane według klucza. Chcę metody, za pomocą której mógłbym uzyskać dostęp do tych poszczególnych grup i uzyskać ich zagregowane wartości. Na przykład w std::multimap< string, int > przechowuję

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

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

Po zapisaniu tych wartości, powinienem być w stanie iterować tę multimapę i uzyskać zagregowane wartości każdej "grupy". Problem w tym, że nie ma żadnych funkcji zdefiniowanych w STL, aby uzyskać dostęp do Multimapy w taki sposób. Przydałoby mi sięlower_bound, upper_bound aby ręcznie iterować multimap i całkowita zawartość grupy, ale mam nadzieję, że będą lepsze sposoby już zdefiniowane w STL ? Czy ktoś może zaproponować rozwiązanie, jak Mogę uzyskać wartości zagregowane dla grupy w powyższym przykładzie.

Author: Yamaneko, 2008-10-29

6 answers

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

Jest w jedną stronę.

Edit:

Jeśli nie znasz grupy, której szukasz, a po prostu przechodzisz przez każdą grupę, uzyskanie zakresu następnej grupy można zrobić tak:

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>());
 41
Author: Greg Rogers,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-08 07:26:33
// 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
 22
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-28 19:28:00

Jeśli znasz już klucze, możesz użyć multimap::equal_range, aby uzyskać Iteratory na początku i na końcu grupy; użyj dowolnego standardowego algorytmu, aby uzyskać pożądane wyniki z zakresu. Jeśli nie znasz kluczy, możesz zacząć od begin() i samodzielnie je przeglądać, porównując klucze, aby znaleźć początek każdej nowej grupy.

 11
Author: Mark Ransom,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-25 17:09:12

Można użyć alternatywnego kontenera, który może zawierać sumy zbiorcze każdej grupy. Aby to zrobić, możesz zrobić coś takiego:

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

Oczywiście, jeśli masz Lambda (w C++0x) to może być prościej:

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;
  }
  );
 1
Author: Dean Michael,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-30 06:09:53
equal_range

Składnia:

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

Funkcja equal_range() zwraca dwa Iteratory - jeden do pierwszego elementu zawierającego key, drugi do punktu tuż za ostatnim elementem zawierającym key.

 0
Author: Hayek.Yu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-14 07:56:10

Nie jest to odpowiedź multimap, ale możesz zrobić następujące rzeczy, jeśli tak zdecydujesz.

#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";
        }
    }
}
 -1
Author: Shadow2531,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-29 19:02:07