How can I sort a vector with pairs by the second element in the opposite order if the first elements are equal?

Viewed 276

I have a vector with pairs in it like so: vector<pair<int, string>> results; I want to sort the vector first by the first elements (the integers) in descending order. If the first elements are equal, I then want to sort by the second elements in ascending order (alphabetical since they are strings). How can I do this?

3 Answers

As @Lala5th says, you can do:

std::sort (results.begin (), results.end (),
    [] (const pair <int, string> &e1, const pair <int, string> &e2)
        { return (e1.first != e2.first) ? e2.first < e1.first :
              e1.second < e2.second; });

Using a lambda keeps all the code in one place.

I think I've got the comparator function the right way round.

Use std::sort and pass in a custom comparator. the example below will do what you want.

#include <iostream>
#include <vector>
#include <utility>
#include <algorithm>
#include <string>

using namespace std;

bool customCompare(pair<int, string> pair1, pair<int, string> pair2) {
    if (pair1.first == pair2.first)
    {
        return pair1.second < pair2.second;
    }

    return pair1.first > pair2.first;
}

int main() {
    vector<pair<int, string> > pairVec;
    pairVec.push_back(pair<int, string>(1, "one"));
    pairVec.push_back(pair<int, string>(2, "btwo"));
    pairVec.push_back(pair<int, string>(2, "atwo"));
    pairVec.push_back(pair<int, string>(3, "three"));

    sort(pairVec.begin(), pairVec.end(), customCompare);


    for (int i = 0; i < pairVec.size(); ++i) {
        cout << pairVec[i].first << "\t" << pairVec[i].second << endl;
    }

    return 0;
}

You should use std::tie when you need to compare multiple members of a pair (or tuple) to each other, taking care to compare members in the order you want:

auto comp = [](auto const &e1, auto const &e2)
{ 
  return std::tie(e2.first, e1.second) 
       < std::tie(e1.first, e2.second);
};

and you would pass this comparator to std::sort.

Related