Keep the order of unordered_map as we insert a new key

Remarkably common request without too many clean,simple solutions. But here they are:

  1. The big library: https://www.boost.org/doc/libs/1_71_0/libs/multi_index/doc/tutorial/index.html Use unique index std::string (or is it char?) and sequenced index to retain the order.
  2. Write it yourself using 2 STL containers: Use a combination of std::unordered_map (or std::map if you want sorted key order traverse as well) and a vector to retain the sequenced order. There are several ways to set this up, depending on the types on your keys/values. Usually keys in the map and the values in the vector. then the map is map<"key_type",int> where the int points to the element in the vector and therefore the value.

I might have a play with a simple template for a wrapper to tie the 2 STL containers together and post it here later...

I have put a proof of concept up for review here:

I went with std::list to store the order in the end, because I wanted efficient delete. But You might choose std::vector if you wanted random access by insertion order.

I used a a list of Pair pointers to avoid duplicate key storage.


No, it is not possible.

Usage of std::unordered_map doesn't give you any guarantee on element order.

If you want to keep elements sorted by map keys (as seems from your example) you should use std::map.

If you need to keep list of ordered pairs you can use std::vector<std::pair<std::string,int>>.


Not with an unordered associative data structure. However, other data structures preserve order, such as std::map which keeps the data sorted by their keys. If you search Stackoverflow a little, you will find many solutions for a data structure with fast key-based lookup and ordered access, e.g. using boost::multi_index.

If it is just about adding values to a container, and taking them out in the order of insertion, then you can go with something that models a queue, e.g. std::dequeue. Just push_back to add a new value, and pop_front to remove the oldest value. If there is no need to remove the values from the container then just go with a std::vector.

Tags:

C++

C++11