Alok
Alok

Reputation: 2035

How to sort a sorted vector while maintaining the previous orders

I have following structure

struct Mydate
{
 int  UserId;
 string name;

};
vector<Mydate> v1;

1: sort the vector by UserId

2: Sort the sorted vector by name while maintaining the previous order For example

v1.push_back(make_pair(100, "d"));
v1.push_back(make_pair(100, "q")); 
v1.push_back(make_pair(102, "m"));
v1.push_back(make_pair(102, "d"));
v1.push_back(make_pair(100, "c"));

( sort function can be used first for UserId but when we sort it agin by name, it override the previous order)

can we see output in follwoing format:

(100,c) , (100, d), (100, q), (102,d), (102, m) 

Please can some one help me out??

Upvotes: 2

Views: 1205

Answers (5)

Vlad from Moscow
Vlad from Moscow

Reputation: 310980

It seems you mean the following

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

struct Mydate
{
    int  UserId;
    std::string name;
};

std::vector<Mydate> v1;

int main()
{
    v1.push_back( { 100, "d" } );
    v1.push_back( { 100, "q" } ); 
    v1.push_back( { 102, "m" } );
    v1.push_back( { 102, "d" } );
    v1.push_back( { 100, "c" } );

    std::sort( v1.begin(), v1.end(),
               []( const Mydate &a, const Mydate &b ) 
               { 
                   return std::tie( a.UserId, a.name ) < std::tie( b.UserId, b.name );
               } );

    for ( const Mydate &item : v1 ) 
    {
        std::cout << item.UserId << '\t' << item.name << std::endl;
    }
}

The program output is

100 c
100 d
100 q
102 d
102 m

Upvotes: 3

Drop
Drop

Reputation: 13003

If you insist on sorting in 2 passes, use std::stable_sort for the second pass.

Upvotes: 1

Revolver_Ocelot
Revolver_Ocelot

Reputation: 8785

Custom comparator approach is preferred one, but, for sake of completeness, multiple sorting approach should be mentioned. Sometimes it might be preferred (usually when you want to be able to choose sorting rules dynamically).

To sort entries by some property A, where elements with same A would be sorted by property B, you need to use bottoms-up approach: sort by B first, then sort by A, preserving relative order of equivalent elements (stable sort).

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

struct Mydate
{
    int  UserId;
    std::string name;
};

int main()
{
    std::vector<Mydate> v {{100, "d"}, {100, "q"}, {102, "m"}, {102, "d"}, {100, "c"}};
    std::sort(v.begin(), v.end(),        [](auto& l, auto& r){return l.name   < r.name;});
    std::stable_sort(v.begin(), v.end(), [](auto& l, auto& r){return l.UserId < r.UserId;});
    for(const auto& d: v)
        std::cout << d.UserId << ' ' << d.name << '\n';
}

Upvotes: 2

Dimitrios Bouzas
Dimitrios Bouzas

Reputation: 42909

You can define your own comparator for std::sort

vector<Mydate> v1;
// ...
std::sort(v1.begin(), v1.end(), [](Mydate const &a, Mydate const &b) {
    return (a.UserId == b.UserId)? (a.name < b.name) : (a.UserId < b.UserId);});

Or instead of a class you can use a std::pair:

using Mydate = std::pair<int, std::string>;

std::pairs are compared lexicographically which is what you want. And then use std::sort as:

std::vector<Mydate> v1;
//...
std::sort(v1.begin(), v1.end());

Upvotes: 3

Anon Mail
Anon Mail

Reputation: 4770

You can define an operator< member function like this:

operator<(const Mydate & rhs)
{
    if (UserId < rhs.UserId)
    {
        return true;
    }
    else if (UserId == rhs.UserId)
    {
        if (name < rhs.name)
        {
            return true;
        }
    }
    return false;
}

Upvotes: 4

Related Questions