Reputation: 2035
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
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
Reputation: 13003
If you insist on sorting in 2 passes, use std::stable_sort
for the second pass.
Upvotes: 1
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
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::pair
s 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
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