2

What I am looking to do is sort a vector of pairs in a way where the first value is lowest to greatest and the second being greatest to lowest and having priority over the first value ordering whilst keeping them together. For example, let's say I had this code:

#include <iostream>
#include <vector>

using namespace std;

int main()
{
    pair<int, double> p;
    vector<pair<int, double> > vp;
    p.first = 2;
    p.second = 2.4;
    vp.push_back(p);
    
    p.first = 9;
    p.second = 3.0;
    vp.push_back(p);
    
    p.first = 10;
    p.second = 3.1;
    vp.push_back(p);
    
    p.first = 1;
    p.second = 2.4;
    vp.push_back(p);
    
    p.first = 5;
    p.second = 3.1;
    vp.push_back(p);
}

if I were to print it out via loop I'd want it to go from outputting this:

2, 2.4
9, 3.0
10, 3.1
1, 2.4
5, 3.1

to outputting this

5, 3.1
10, 3.1
9, 3.0
1, 2.4
2, 2.4

Now imagine if those values weren't given manually but instead they were random and being randomized over a for loop that loops a random amount of times from between 0 and 100 inclusive each time the code is run, each new random value of both sides of the pair being stored in the vector (which would give the vector a size of 10.)

How do I sort out the vector so it would have output that is ordered the same as the above example?

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
Shadow
  • 25
  • 3

2 Answers2

2

The simplest way is to use the standard functions std::sort() and std::tie().

Here is a demonstration program:

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

int main()
{
    std::vector<std::pair<int, double>> v =
    {
        {  2, 2.4 },
        {  9, 3.0 },
        { 10, 3.1 },
        {  1, 2.4 },
        {  5, 3.1 }
    };

    std::sort( std::begin( v ), std::end( v ),
               []( const auto &p1, const auto &p2 )
               {
                   return std::tie( p2.second, p1.first ) < std::tie( p1.second, p2.first );
               } );

    for (const auto &p : v)
    {
        std::cout << p.first << ' ' << p.second << '\n';
    }
}

The program output is:

5 3.1
10 3.1
9 3
1 2.4
2 2.4
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • I'm still learning so I ask what does 'auto' do. also the problem with sort is it sorts based on one value of an object rather than two so while I could sort by the second it would just end up as 10, 3.1 5, 3.1 9, 3.0 2, 2.4 1, 2.4 rather than the output. As far as coding in c++ goes, as I stated I am barely scratching the surface so I don't know what &variable does or what the colon in a for loop does (I have seen them used from through looking for other things but don't know what they do) But I can try this with a little research on the tie function. – Shadow Jan 11 '22 at 15:39
  • @Shadow You need to read a book for beginners on C++. For example & in a declaration means a reference. auto is a type specifier that is deduced by the compiler. For example in this for loop for (const auto &p : v) the specifier auto may be substituted for for ( const std::pair &p : v ) – Vlad from Moscow Jan 11 '22 at 15:44
  • So I tried it, it worked, but there was one problem: it printed everything three times. – Shadow Jan 11 '22 at 16:29
  • @Shadow In the demonstration program I showed there is only one output of the vector. – Vlad from Moscow Jan 11 '22 at 17:02
  • Well I just ran it, every time I ran it using the answer you gave me things printed 3 times. I'll be posting a question as to how I can clean up my code and make it look nicer shortly, hopefully that will allow me to find out why it's printing everything 3 times – Shadow Jan 11 '22 at 20:03
0

Use std::sort() with a custom comparator, eg:

#include <algorithm>

std::sort(vp.begin(), vp.end(),
    [](const std::pair<int, double> &p1, const std::pair<int, double> &p2){
        if (p1.second > p2.second) return true;
        if (p1.second < p2.second) return false;
        return p1.first < p2.first;
    }
);

Output:

5, 3.1
10, 3.1
9, 3
1, 2.4
2, 2.4

Online Demo

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • That would just return the values in the order of the second value but printing them in the order of top to bottom when it comes to the first value – Shadow Jan 11 '22 at 15:41
  • @Shadow it outputs exactly what you asked for. Did you even look at the demo I linked to? – Remy Lebeau Jan 11 '22 at 15:52