22

I inserted the elements to the unordered_map with this code:

    myMap.insert(std::make_pair("A", 10));
    myMap.insert(std::make_pair("B", 11));
    myMap.insert(std::make_pair("C", 12));
    myMap.insert(std::make_pair("D", 13));

But when I used this command to print the keys

for (const auto i : myMap)
{
    cout  << i.first << std::endl;
}

they are not in the same order as I inserted them.

Is it possible to keep the order?

Marco A.
  • 43,032
  • 26
  • 132
  • 246
user1436187
  • 3,252
  • 3
  • 26
  • 59

3 Answers3

25

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>>.

Pustovalov Dmitry
  • 998
  • 1
  • 9
  • 25
9

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.

Jens
  • 9,058
  • 2
  • 26
  • 43
4

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.

Oliver Schönrock
  • 1,038
  • 6
  • 11