Сортировка std:: unordered_map по ключу

Как я могу сортировать unordered_map по ключу? Мне нужно напечатать unordered_map отсортированный по ключу.

Ответ 1

std::unordered_map<int, int> unordered;

std::map<int, int> ordered(unordered.begin(), unordered.end());
for(auto it = ordered.begin(); it != ordered.end(); ++it)
     std::cout << it->second;

Ответ 2

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

std::unordered_map<KeyType, MapType> unordered;
std::vector<KeyType> keys;

keys.reserve (unordered.size());
for (auto& it : unordered) {
    keys.push_back(it.first);
}
std::sort (keys.begin(), keys.end());
for (auto& it : keys) {
    std::cout << unordered[it] << ' ';
}

Ответ 3

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

Если вы это сделаете, получите нормальный map. Ключи автоматически сортируются в строго-слабом порядке. Если вам нужен другой вид, напишите свой собственный компаратор.

Если вам нужно только отсортировать его, следующее может быть неэффективным, но оно будет как можно ближе, если вы все еще хотите сохранить unordered_map.

#include <map>
#include <unordered_map>
#include <algorithm>
#include <iostream>
#include <functional>

struct map_streamer{
  std::ostream& _os;

  map_streamer(std::ostream& os) : _os(os) {}

  template<class K, class V>
  void operator()(std::pair<K,V> const& val){
    // .first is your key, .second is your value
    _os << val.first << " : " << val.second << "\n";
  }
};

template<class K, class V, class Comp>
void print_sorted(std::unordered_map<K,V> const& um, Comp pred){
  std::map<K,V> m(um.begin(), um.end(), pred);
  std::for_each(m.begin(),m.end(),map_streamer(std::cout));
}

template<class K, class V>
void print_sorted(std::unordered_map<K,V> const& um){
  print_sorted(um, std::less<int>());
}

Пример в Ideone.
Обратите внимание, что в С++ 0x вы можете заменить две перегрузки одной функцией аргументом шаблона по умолчанию:

template<class K, class V, class Comp = std::less<int> >
void print_sorted(std::unordered_map<K,V> const& um, Comp pred = Comp()){
  std::map<K,V> m(um.begin(), um.end(), pred);
  std::for_each(m.begin(),m.end(),map_streamer(std::cout));
}