1

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>
NutCracker
  • 11,485
  • 4
  • 44
  • 68
Lilith X
  • 99
  • 1
  • 9
  • 1
    Does this answer your question? [How does std::sort work for list of pairs?](https://stackoverflow.com/questions/23816797/how-does-stdsort-work-for-list-of-pairs) – NutCracker Feb 03 '20 at 07:02
  • Using `std::vector` instead of `std::list` changes the answer, consider asking a fresh new answer for `std::vector`. – JFMR Feb 03 '20 at 07:12

3 Answers3

4

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);
 });
JFMR
  • 23,265
  • 4
  • 52
  • 76
  • Sorry, I'm very new to programming. So in my header file, do I put bool sortbysecond([](auto const& a, auto const& b) { return std::tie(b.second, a.first) < std::tie(a.second, a.first); }); and then on my cpp file, i can use it as sort(words.begin(), words.end(), sortbysecond); – Lilith X Feb 03 '20 at 08:21
  • @LilithX you use it as `words.sort(...)`. It is a *member function* of `std::list`. You can, however, use that predicate for `std::sort()` for sorting an `std::vector` as well. – JFMR Feb 03 '20 at 08:27
  • If you want to write a function instead of a lambda it would be then `bool sortbysecond(const std::pair &a, const std::pair &b) { return std::tie(b.second, a.first) < std::tie(a.second, a.first); }`. – JFMR Feb 03 '20 at 08:28
  • ah! It compiled successfully! Do you happen to know how i could iterate through my sorted list so I could print them out and see if they indeed sorted correctly? Thank you very much! – Lilith X Feb 03 '20 at 08:37
  • @LilithX `for (auto const& p: vec) std::cout << p.first << ' ' < p.second << '\n';` should do the trick. Remember that the elements are pairs. – JFMR Feb 03 '20 at 08:39
  • 1
    it did indeed! Thank you very much for your help! – Lilith X Feb 03 '20 at 09:03
1

std::list has a member function std::list::sort that is supposed to do the sorting.

One of its two overloads accepts custom comparison function:

template <class Compare>
void sort(Compare comp);

which you can use as follows:

words.sort([](const std::pair<string, unsigned int> &x,
              const std::pair<string, unsigned int> &y)
{
    return x.second > y.second;
});
NutCracker
  • 11,485
  • 4
  • 44
  • 68
-1

We are creating a compare function in bool which compares two pairs' second values and give the return bigger value first and simply done sorting with using that function.

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;


bool compare(const pair<int,int>& a, const pair<int,int>& b){
    return a.second > b.second;
}

int main() {
    vector<pair<int,int>> v = {{1, 5}, {2, 3}, {3, 8}, {4, 2}, {5, 1}};
    
    // sorting the vector of pairs by second value
    sort(v.begin(), v.end(), compare);
    
    // printing the sorted vector of pairs
    for(auto x: v){
        cout << x.first << " " << x.second << endl;
    }
    
    return 0;
}
Benjamin Buch
  • 4,752
  • 7
  • 28
  • 51
  • Don't post "code only" answers. Explain what you are doing and why it solves the problem. – Jesper Juhl Mar 13 '23 at 10:49
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Mar 17 '23 at 16:18