Iterate over keys in map from largest length to smallest length

I am trying to iterate over all keys in a map. I have this code:

map<string, array<string, 3>> dat;
array<string, 3> dt({ "var","TEXT","" });
dat["atest"] = dt;
array<string, 3> at({ "var","DATA","" });
dat["testplusalot"] = at;
array<string, 3> t({ "var","NONE","" });
dat["testalot"] = t;
for (const auto& p : dat) {
    cout << p.first << endl;
}

I want it to say

testplusalot
testalot 
atest

but I get

atest
testalot
testplusalot

how could I do this.


Solution 1:

Since you want to order the keys by length, and then if the lengths are the same, order them alphabetically (the simplest fall-back ordering), then the following can be done:

#include <map>
#include <string>
#include <array>
#include <iostream>

// Create a type that describes the sort order
struct strCompare 
{
    bool operator()(const std::string& Left, const std::string& Right) const 
    {
        // Sort by length 
        if ( Left.length() != Right.length() )
            return Left.length() > Right.length();

       // Fall back to string < ordering
        return Left < Right;            
    }
};

int main()
{
    std::map<std::string, std::array<std::string, 3>, strCompare> dat;
    std::array<std::string, 3> dt({ "var","TEXT","" });
    dat["atest"] = dt;
    std::array<std::string, 3> at({ "var","DATA","" });
    dat["testplusalot"] = at;
    std::array<std::string, 3> t({ "var","NONE","" });
    dat["testalot"] = t;
    std::array<std::string, 3> t2({ "var","NONE","" });
    dat["testblot"] = t2;
    for (const auto& p : dat) {
        std::cout << p.first << std::endl;
    }   
}

Output:

testplusalot
testalot
testblot
atest

The strCompare is a type that has an overloaded < that determines the key sort criteria.

Then the creation of the std::map requires that you specify the sort ordering in the third template parameter:

std::map<std::string, std::array<std::string, 3>, strCompare> dat;