stl::multimap - كيف يمكنني الحصول على مجموعات من البيانات؟

StackOverflow https://stackoverflow.com/questions/247818

  •  05-07-2019
  •  | 
  •  

سؤال

يحتوي Multimap بشكل أساسي على مجموعات من البيانات مرتبة حسب المفتاح.أريد طريقة يمكنني من خلالها الوصول إلى هذه المجموعات الفردية والحصول على قيمها الإجمالية.على سبيل المثال، في أ std::multimap< string, int > أنا أخزن

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

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

بعد تخزين هذه القيم، يجب أن أكون قادرًا على تكرار هذه الخريطة المتعددة والحصول على القيم الإجمالية لكل "مجموعة".تكمن المشكلة في عدم وجود أي وظائف محددة في STL للوصول إلى MultiMaps بهذه الطريقة.يمكن أن أستخدم lower_bound, upper_bound لتكرار الخريطة المتعددة يدويًا وإجمالي محتويات المجموعة، ولكنني آمل أن تكون هناك طرق أفضل محددة بالفعل في STL؟هل يمكن لأي شخص أن يقترح حلاً لكيفية الحصول على القيم الإجمالية لمجموعة في المثال أعلاه.

هل كانت مفيدة؟

المحلول

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

نصائح أخرى

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

إذا كنت تعرف مفاتيح، يمكنك استخدام multimap::equal_range للحصول على التكرارات إلى بداية ونهاية الجماعة؛ استخدام أي خوارزمية القياسية للحصول على النتائج المرجوة من مجموعة. إذا كنت لا تعرف مفاتيح، يمكنك البدء في begin() وتكرار خلال بنفسك، مقارنة مفاتيح للعثور على بداية كل مجموعة جديدة.

ويمكنك استخدام وعاء البديلة التي يمكن أن تحتوي على المبالغ الإجمالية لكل مجموعة. للقيام بذلك قد تفعل شيئا مثل:

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

وبطبيعة الحال، إذا كان لديك لامبدا (باللغة 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;
  }
  );
equal_range

وبناء الجملة:

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

ووequal_range() وظيفة يعود اثنين المكررات - واحدة إلى العنصر الأول الذي يحتوي على مفتاح، وآخر إلى نقطة فقط بعد العنصر الأخير الذي يحتوي على مفتاح.

وليس إجابة multimap، ولكن يمكنك أن تفعل أشياء مثل التالية إذا اخترت ذلك.

#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";
        }
    }
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top