Итерация по hash_multimap по ключу, а затем по значению - PullRequest
0 голосов
/ 10 сентября 2011

Мне нужно выполнить некоторый код для всех значений ключа, и мне нужно повторить это действие для каждого ключа.Я ищу что-то вроде:

for(auto key_iterator = hash_multimap.begin_keys();
    key_iterator != hash_multimap.end_keys(); key_iterator++)
{
    auto key = key_iterator->key;
    // set up state
    for(auto value_iterator = key_iterator->begin_values();
        value_iterator != key_iterator->end_values(); value_iterator++)
    {
        // mutate state
    }
    // use state
    // tear down state
}

Это, конечно, не работает, но есть ли способ добиться подобного эффекта?проблема в том, что мне нужно пройти через каждый ключ, а затем использовать общее состояние для всех них.Пример того, для чего он может быть использован:

typedef std::hash_multimap<int> hash_t;
typedef hash_t::value_type hash_val;

hash_t hash;
hash.insert(hash_val(0, 1));
hash.insert(hash_val(1, 2));
hash.insert(hash_val(1, 3));
hash.insert(hash_val(2, 4));
hash.insert(hash_val(2, 5));
hash.insert(hash_val(2, 6));
hash.insert(hash_val(3, 7));
hash.insert(hash_val(3, 8));
hash.insert(hash_val(3, 9));

// print out the sum of values for each key here.
// expected output:
//
// 0: 1
// 1: 5
// 2: 15
// 3: 24

Проблема с использованием hash_multimap.begin() заключается в том, что я не могу быть уверен, что он возвращает каждый ключ в последовательном блоке этого ключа, и дажеесли это произойдет, я не могу знать, где такой блок начинается и где он заканчивается.

Редактировать: я также не могу использовать hash_multimap.equal_range(key), потому что я не могу перебирать ключи.способ перебора ключей, включающий каждый ключ только один раз, также решит эту проблему.

Как я могу это сделать?

Ответы [ 2 ]

1 голос
/ 10 сентября 2011

Вы можете использовать нижнюю границу и верхнюю границу для достижения этой цели.Например, попробуйте -

 auto value_iterator = hash->begin();
 while( value_iterator != hash->end() ){
 {
     auto lIter = hash->lower_bound( value_iterator->first );
     auto uIter = hash->upper_bound( value_iterator->first );
     while( lIter != uIter ){
         // sum the values associated with keys
         // Increment lIter
     }
     value_iterator = uIter;
 }

Редактировать: вы можете использовать equal_range, как предложено @Tanatos, если используемая вами библиотека не имеет функций-членов upper_bound, lower_bound. Microsoft Реализация действительно имеет это.Логика та же, и внутренний цикл будет -

pair<hash_multimap<int,int>::iterator,hash_multimap<int,int>::iterator> pairIter;
pairIter.equal_range(value_Iterator->first);
while( pairIter.first != pairIter.second ){
    // sum the values associated with keys
    // Increment pairIter->first
}
value_iterator = pairIter.second;
0 голосов
/ 10 сентября 2011

Так как вы использовали синтаксис C ++ 11, я тоже буду; -]

#include <algorithm>
#include <numeric>
#include <unordered_map>
#include <iostream>

int main()
{
    typedef std::unordered_multimap<int, int> map_t;
    typedef std::unordered_map<int, int> sums_t;

    map_t hash;
    hash.insert(map_t::value_type(0, 1));
    hash.insert(map_t::value_type(1, 2));
    hash.insert(map_t::value_type(1, 3));
    hash.insert(map_t::value_type(2, 4));
    hash.insert(map_t::value_type(2, 5));
    hash.insert(map_t::value_type(2, 6));
    hash.insert(map_t::value_type(3, 7));
    hash.insert(map_t::value_type(3, 8));
    hash.insert(map_t::value_type(3, 9));

    sums_t const& sums = std::accumulate(hash.cbegin(), hash.cend(), sums_t(),
        [](sums_t& acc, map_t::const_reference p)
        {
            return acc[p.first] += p.second, acc;
        }
    );

    std::for_each(sums.cbegin(), sums.cend(),
        [](sums_t::const_reference p)
        {
            std::cout << p.first << ": " << p.second << '\n';
        }
    );
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...