Zack Lee
Zack Lee

Reputation: 3044

How to sort a std::map by ascending order of value?

I'm trying to figure out how to sort std::map by ascending order of value.

My Code :

#include <iostream>
#include <map>
#include <string>
#include <iterator>

void printMapByOrder(std::map<std::string, int> mapOfPlanets)
{
    //what should be here?
}

int main() {

    std::map<std::string, int> mapOfPlanets;
    mapOfPlanets["earth"] = 12;
    mapOfPlanets["jupiter"] = 142;
    mapOfPlanets["mars"] = 6;
    mapOfPlanets["mercury"] = 4;
    mapOfPlanets["neptune"] = 49;
    mapOfPlanets["pluto"] = 2;
    mapOfPlanets["saturn"] = 120;
    mapOfPlanets["uranus"] = 51;
    mapOfPlanets["venus"] = 12;
    printMapByOrder(mapOfPlanets);
}

The Result I want :

 pluto : 2
 mercury : 4
 mars : 6
 earth : 12
 venus : 12
 neptune : 49
 uranus : 51
 saturn : 120
 jupiter : 142

Is this possible to do this with std::map?

Upvotes: 0

Views: 2327

Answers (2)

Toby Speight
Toby Speight

Reputation: 30822

A std::map is ordered by its keys, and that can't be changed (after all, the point of a map is fast access by key). You could, however, create a container of pointers to your map elements, and sort that for printing. You'll want to pass your map by const reference, so that your pointers won't be invalidated:

#include <algorithm>
#include <vector>

void printMapByOrder(const std::map<std::string, int>& mapOfPlanets)
{
    using element = typename std::map<std::string, int>::value_type;
    std::vector<const element*> sorted;
    sorted.reserve(mapOfPlanets.size());
    for (auto& planet: mapOfPlanets)
        sorted.push_back(&planet);

    # sort by value
    std::sort(sorted.begin(), sorted.end(),
              [](auto *a, auto *b) {
                  return std::tie(a->second, a->first)
                      <  std::tie(b->second, b->first);
              });

    # print results
    std::transform(sorted.begin(), sorted.end(),
                   std::ostream_iterator<std::string>(std::cout),
                   [](const auto *p) {
                       return p->first + ": "
                           + std::to_string(p->second) + '\n';
                   });
}

Upvotes: 3

darune
darune

Reputation: 10962

No. Its not possible to sort a map by its values.

One possible solution:

void printMapByOrder(std::map<std::string, int> mapOfPlanets)
{
    std::vector < std::pair<std::string, int> > planets(mapOfPlanets.begin(), mapOfPlanets.end());
    std::sort(planets.begin(), planets.end(), [](auto lhs, auto rhs) {return lhs.second < rhs.second; });
    //print planets
}

Upvotes: 4

Related Questions