web-dev-qa-db-ja.com

stl :: multimap-データのグループを取得するにはどうすればよいですか?

マルチマップには基本的に、キーでソートされたデータのグループがあります。これらの個々のグループにアクセスして、それらの集計値を取得できる方法が必要です。たとえば、std::multimap< string, int >保管

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

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

これらの値を保存したら、このマルチマップを反復して、各「グループ」の集計値を取得できるはずです。問題は、そのような方法でMultiMapにアクセスするためのSTLで定義された関数がないことです。 lower_boundupper_boundマルチマップを手動で反復してグループのコンテンツを合計するには、STLですでに定義されているより良い方法があることを望んでいますか?上記の例でグループの集計値を取得する方法についての解決策を誰かが提案できますか?.

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

片道です。

編集:

探しているグループがわからず、各グループを調べているだけの場合、次のグループの範囲を取得するには、次のようにします。

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>());
40
Greg Rogers
// 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
21
Roger House

キーがすでにわかっている場合は、_multimap::equal_range_を使用して、イテレータをグループの先頭と末尾に移動できます。任意の標準アルゴリズムを使用して、範囲から目的の結果を取得します。キーがわからない場合は、begin()から開始して自分で反復し、キーを比較して新しいグループの先頭を見つけることができます。

11
Mark Ransom

各グループの合計を含むことができる代替コンテナを使用できます。これを行うには、次のようにします。

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

もちろん、Lambda(C++ 0xの場合)を使用している場合は、より単純になる可能性があります。

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
Dean Michael
_equal_range
_

構文:

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

関数equal_range()は2つのイテレータを返します。1つはキーを含む最初の要素へのイテレータ、もう1つはキーを含む最後の要素の直後のポイントへのイテレータです。

0
Hayek.Yu