Yeasin Rahaman
Yeasin Rahaman

Reputation: 119

vector pair sorting by the difference of the pair elements

Is there any way in C++, That will sort me a pairs of vector based on the difference of the pair values. As an example, Suppose I have 4 pairs

1 3, 
5 6, 
2 3,
12 5,

so, the differences of the pairs are 2 1 1 7, if I sort in descending order The sorted vector would be,

12 5,
1 3,
5 6,
2 3,

I hope you understood what my problem is. Is there any way to sort the elements this way?

I have tried this way to sort elements based on first or second element. But this is not my problem. My problem is I need sort that based on the difference.

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


int main()
{
    vector< pair <int,int> > pq;
    for(int i=1; i<=4; i++){
        int x,y;
        cin >> x >> y;

        pq.push_back(make_pair(x,y));
    }

    sort(pq.begin(), pq.end(), sortinrev);

    for(int i=0; i<4; i++){
        cout << pq[i].first << " " << pq[i].second << endl;
    }


    return 0;
}

Upvotes: 4

Views: 2585

Answers (3)

Stephan Lechner
Stephan Lechner

Reputation: 35154

The standard library provides a data structure std::pair and a sorting algorithm std::sort, to which you can pass your custom comparison that defines the order. See the following code, that defines a comparator taking two std::pair<int,int> and comparing them based on their "absolute difference", together with the code how to invoke std::sort with it. Hope it helps.

#include <iostream>
#include <vector>

int main()
{
    std::vector<std::pair<int,int> > v = {
        {1, 3},
        {5, 6},
        {2, 3},
        {12, 5}
    };

    // sort using a custom function object
    struct {
        bool operator()(const std::pair<int,int> &a, const std::pair<int,int> &b) const
        {
            return ( abs(a.first-a.second) > abs(b.first-b.second));
        }
    } differenceIsGreater;
    std::sort(v.begin(), v.end(), differenceIsGreater);
    for (auto a : v) {
        std::cout << "(" << a.first << "," << a.second << ")" << std::endl;
    }

    return 0;
}

Output:

(12,5)
(1,3)
(5,6)
(2,3)

Upvotes: 2

Rex Kerr
Rex Kerr

Reputation: 91

std::sort has an overload that takes a compare callable.

template< class RandomIt, class Compare >
void sort( RandomIt first, RandomIt last, Compare comp );

So, you can pass a lambda (or other function) as that third parameter that tcompares any way that you want.

From cppreference.com:

comp     -   comparison function object (i.e. an object that satisfies the     requirements of Compare) which returns ​true if the first argument is less than (i.e. is ordered before) the second. 
The signature of the comparison function should be equivalent to the following:

bool cmp(const Type1 &a, const Type2 &b);

The signature does not need to have const &, but the function object must not modify the objects passed to it.
The types Type1 and Type2 must be such that an object of type RandomIt can be dereferenced and then implicitly converted to both of them. ​

So, for example

sort(begin(myvect), end(myvect), [](auto p) { /* comparison code */ });

(that requires c++14, you may have to modify that depending on your compiler version)

Upvotes: 1

Cory Kramer
Cory Kramer

Reputation: 117856

If your container is

std::vector<std::pair<int, int>> data;

you could sort it as

std::sort(std::begin(data),
          std::end(data),
          [](std::pair<int, int> const& lhs, std::pair<int, int> const& rhs)
          {
              return std::abs(lhs.first - lhs.second) < std::abs(rhs.first - rhs.second);
          });

If you want to switch between ascending and descending just switch from < to > accordingly.

Upvotes: 8

Related Questions