boost :: unordered_multimap: получить все элементы в корзине эффективно?

0

Я могу получить все элементы в одном ведре с помощью этого кода:

typedef boost::unordered_multimap< key, myClass*, MyHash<key> >
                                                HashMMap;
HashMMap::iterator it;
it = hashMMap_.find( someKey);
int bucketIndex = hashMMap_.bucket( someKey);
int bucketSize = hashMMap_.bucket_size( bucketIndex);

qDebug() << "index of bucket with key:" << someKey << " is:"
         << bucketIndex;
qDebug() << "number of elements in bucket with index:" << bucketIndex << " is:"
         << bucketSize;

HashMMap::local_iterator lit;
/* begin of bucket with index bucketIndex */
lit = hashMMap_.begin( bucketIndex);

for ( ; lit != sender_.hashMMap_.end( bucketIndex); ++lit) {
    qDebug() << "(*lit).first:" << (*lit).first << ", (*lit).second:" <<
               (*lit).second << ", (*lit).second->something_:" <<
               (*lit).second->something_;
}

Я хотел бы получить local_iterator для первого элемента в ведре и перебрать его до конца ведра, поэтому, если в хэш-таблице есть только одно значение для данного индекса (где index - это Hash(key)), я буду перебирать просто через один элемент и получить конец ведра(), а в случае многих элементов я буду перебирать целую ведро (все значения с равным хешем). возможно ли это без bucketIndex, hashMMap_.begin( bucketIndex) и hashMMap_.end( bucketIndex)?

поэтому в основном я хотел бы получить local_iterator следующим образом:

HashMMap::local_iterator lit = hashMMap_.find_bucket_if_present( someKey);

Дополнительный вопрос: должен ли я сначала проверить, если find() возвращает итератор элементу перед вызовом int bucketIndex = hashMMap_.bucket( someKey)? Это то, что я думаю, потому что объяснение функции bucket() от сайта boost:

Возвраты: индекс ведра, который будет содержать элемент с ключом k.

                                 ^^^

Я думаю, это означает, что я должен сначала find(key) в мультимаре, чтобы узнать, присутствует ли ключ, потому что вызов в bucket(key) возвращает индекс, который не является хешем, а bucket_from_hash хеша (bucket_from_hash) в хеш-таблице под которым ключ хранится, если он присутствует. Поэтому из-за bucket_count, который выполняется с помощью bucket_count, если ключ не был вставлен, я буду перебирать виртуальное ведро, в котором он будет находиться в текущих обстоятельствах, и что для меня наиболее важно: также могут существовать различные хэши, поскольку bucket_count может быть меньше, чем мой хэш (я использую 16-разрядный MyHash<key> 32-битного ключа как хэш-функцию, предоставленную в конструктор multimap). Это верно?

  • 0
    Я не совсем понимаю. Разве ваш код не выполняет именно то, что вы уже просили?
  • 0
    Вероятно, если есть другой способ, он будет делать то же самое, что я делаю с bucketIndex, но я хотел бы быть уверен, что я не пропускаю ни одной функциональности этого контейнера, и действительно, я должен найти корзину самостоятельно
Показать ещё 1 комментарий
Теги:
boost
bucket
multimap
boost-unordered

1 ответ

3
Лучший ответ

Я бы начал работать с диапазонами, например:

template<typename BoostUnorderedMap, typename Key>
boost::iterator_range< typename BoostUnorderedMap::local_iterator > get_bucket_range( BoostUnorderedMap& myMap, Key const& k ) {
  int bucketIndex = myMap.bucket( k );
  return boost::iterator_range< typename BoostUnorderedMap::local_iterator >(
    myMap.begin(bucketIndex),
    myMap.end(bucketIndex)
  }
}
template<typename BoostUnorderedMap, typename Key>
boost::iterator_range< typename BoostUnorderedMap::local_const_iterator > get_bucket_range( BoostUnorderedMap const& myMap, Key const& k ) {
  int bucketIndex = myMap.bucket( k );
  return boost::iterator_range< typename BoostUnorderedMap::local_const_iterator >(
    myMap.begin(bucketIndex),
    myMap.end(bucketIndex)
  }
}

то, по крайней мере, на С++ 11 вы можете сделать следующее:

for (auto && entry : get_bucket_range( some_map, "bob" ) )

и он повторяет все в ведро "bob".

Хотя это использует bucketIndex, он скрывает эти данные от конечного пользователя и просто дает вам boost::range.

  • 0
    спасибо, это хорошо, хотя я использую c ++ 03, я все еще могу выполнять итерации с помощью local_iterator. Как насчет второй части моего вопроса, безопасно ли вызывать myMap.bucket (k) без предварительного тестирования, если карта на самом деле содержит ключ k?
  • 1
    @ piotruś Я прошелся по файлам boost hpp, и это привело меня к boost.org/doc/libs/1_36_0/boost/unordered/detail/hash_table.hpp, где bucket_from_hash - последний вызов в достаточно глубокой цепочке. Он хэширует ключ (который не заботится о том, находится ли ключ на карте), затем выполняет bucket_from_hash , который просто делает мод. Поэтому, по крайней мере, для файлов, которые я читал, это не требовалось: и я не могу придумать причину, по которой будущая реализация захочет добавить это требование.
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню