Search code examples
c++listsortingstlcontainers

How to sort a list of pairs based on second element in decreasing order in c++


I was wondering if there's a way to sort my list of pairs based on the second element. Here is a code:

std::list<std::pair<std::string, unsigned int>> words;

words.push_back(std::make_pair("aba", 23);
words.push_back(std::make_pair("ab", 20);
words.push_back(std::make_pair("aBa", 15);
words.push_back(std::make_pair("acC", 8);
words.push_back(std::make_pair("aaa", 23);

I would like to sort my list words based in the integer element in decreasing order so that my list would be like:

<"aba", 23>,<"aaa", 23>,<"ab", 20>,<"aBa", 15>,<"acC", 8>

Also, is it possible to sort them by both the first and second element such that it sorts by the second elements first (by integer value), and then if there's two or more pairs with the same second element (i.e. same integer value), then it will sort those based on the first element in alphabetical order, then the first 2 pairs on my sorted list above would swap, so:

<"aaa", 23>,<"aba", 23>,<"ab", 20>,<"aBa", 15>,<"acC", 8>

Solution

  • I would like to sort my list words based in the integer element in decreasing order

    The sorting predicate must return true if the first element (i.e., the first pair) passed precedes the second one in your established order:

    words.sort([](auto const& a, auto const& b) {
          return a.second > b.second;
    });
    

    Since you want to sort the list in decreasing order, the pair a will precede b if its second element (i.e., the int) is greater than b's second element.


    Note that std::sort() doesn't work for sorting an std::list because it requires random access iterators but std::list only provides bidirectional iterators.


    is it possible to sort them by both the first and second element such that it sorts by the second elements first (by integer value), and then if there's two or more pairs with the same second element (i.e. same integer value), then it will sort those based on the first element in alphabetical order

    Assuming again decreasing order for the int element, just resort to the second element of the pairs when both int elements are the same:

       lst.sort([](auto const& a, auto const& b) {
          if (a.second > b.second)
             return true;
          if (a.second < b.second)
             return false;
          return a.first < b.first;
       });
    

    or more concise thanks to std::tie():

    lst.sort([](auto const& a, auto const& b) {
        return std::tie(b.second, a.first) < std::tie(a.second, a.first);
     });