简体   繁体   English

按键排序 std::unordered_map

[英]Sorting std::unordered_map by key

How can I sort an unordered_map by key?如何按键排序unordered_map I need to print an unordered_map sorted by key.我需要打印一个按键排序的unordered_map

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;

An alternate solution is to construct a vector of the keys, sort the vector, and print per that sorted vector.另一种解决方案是构造一个键向量,对向量进行排序,然后按照排序后的向量进行打印。 This will be considerably faster than the approaches that constructed a map from the ordered map, but will also involve more code.这将比从订购的 map 构建 map 的方法快得多,但也会涉及更多代码。

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] << ' ';
}

Are you sure you need this?确定你需要这个吗? Because that is not possible.因为那是不可能的。 An unordered_map is a hash container, that is, the keys are hashed .一个unordered_map是一个 hash 容器,也就是说,键是散列的。 Inside of the container, they don't have the same representation as on the outside.在容器内部,它们与外部的表示不同。 Even the name implies that you can't sort it.甚至名称也暗示您无法对其进行排序。 It's one of the criteria to choose a hash container: You do not need a specific order.这是选择 hash 容器的标准之一:您不需要特定的订单。

If you do, get a normal map .如果你这样做了,得到一个正常的map The keys are automatically sorted in a strict-weak ordering.键自动按严格-弱排序进行排序。 If you need another sort, write your own comparator.如果您需要另一种排序,请编写自己的比较器。

If you only need to print it sorted, the following may be inefficient, but it's as close as you'll get if you still want to keep the unordered_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>());
}

Example on Ideone . Ideone 上的示例
Note that in C++0x, you can replace the two overloads with one function with a default template argument:请注意,在 C++0x 中,您可以使用默认模板参数将两个重载替换为一个 function:

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

Similar to David's answer, we can use std::set to sort the key first:与大卫的回答类似,我们可以先使用std::set对键进行排序:

std::unordered_map<int, int> unordered;
std::set<int> keys;
for (auto& it : unordered) keys.insert(it.first);
for (auto& it : keys) {
    std::cout << unordered[it] << ' ';
}

You can use vector to store your key value pairs, then sort them in vector, put them back at map at last.您可以使用向量来存储您的键值对,然后将它们排序在向量中,最后将它们放回 map。

#include <iostream>                                 
#include <unordered_map>                                 
#include <algorithm>                                 
#include <vector>                                 

using namespace std;                                

int main(){                                
    unordered_map<string, int> sdict = {{"hello", 11 }, {"world", 52}, {"tommy", 3}};               
    unordered_map<string, int> resdict;          

    vector<pair<string, int>> tmp;
    for (auto& i : sdict)                                         
        tmp.push_back(i);                                

    for (auto& i : sdict)       
        cout <<  i.first << " => " << i.second << endl;  

    // sort with descending order.
    sort(tmp.begin(), tmp.end(),                                   
    [&](pair<string, int>& a, pair<string, int>& b) { return a.second < b.second; });

    for (auto& i : tmp)                          
    {                           
        resdict[i.first] = i.second;                   
    }                                

    cout << "After sort." << endl;   
    for (auto& i : resdict)     
        cout <<  i.first << " => " << i.second << endl;           
    return 0;                                              

}                                            

Compile with following commands.使用以下命令编译。

g++ --std=c++11 test_sort_ordered_map.cpp

The result is:结果是:

tommy => 3
hello => 11
world => 52
After sort.
world => 52
hello => 11
tommy => 3

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM