In this example we will discuss different ways to sort a std::list of user defined data types with custom comparators or lambda functions.
Suppose we have a type Player that contains Id and name.
struct Player { int id; std::string name; Player(int playerId, std::string playerName) : id(playerId), name(playerName) { } bool operator <(const Player & playerObj) const { return id < playerObj.id; } };
It has its < operator overloaded, which compares 2 Player objects using < on its ID field.
Now lets create a list of Player objects i.e.
std::list<Player> listofPlayers = { Player(22, "Sid"), Player(3, "Laura"), Player(43, "Riti"), Player(30, "Angel"), Player(2, "Laura"),};
Now we want to sort this list of Players and we are going to use std::list::sort() for this.
std::list::sort
std::list::sort has two different overloaded versions i.e.
void std::list::sort();
It uses the default sorting criteria i.e. will use < opeartor to compare the elements in list while sorting.
template <class Compare> void sort (Compare comparator);
It accepts a Compare function or function object and use this comparator to compare the elements in list while sorting.
Lets discuss each of them,
Sorting a List with Default Criteria
To sort a std::list with default criteria i.e < operator of type, We will use version of sort() function that accepts no arguments i.e.
// Sort List by default criteria i.e < operator of Player listofPlayers.sort();
It will sort the list using < operator of struct Player. Thus all the players will be sorted by their ID i.e.
2 :: Laura 3 :: Laura 22 :: Sid 30 :: Angel 43 :: Riti
Now suppose we want to sort the list of Player objects using their name instead of ID. It cannot be done by using default < operator of Player in sort(). So, we will use other overloaded version of sort().
Sorting a List of Objects with Custom Comparator & Function Object
std::list::sort has an another overloaded version that accepts a function pointer as an argument and use that for comparison while sorting.
template <class Compare> void sort (Compare comparator);
Define a comparator or function object that will compare two Player Objects using their name.
struct PlayerComparator { // Compare 2 Player objects using name bool operator ()(const Player & player1, const Player & player2) { if(player1.name == player2.name) return player1 < player2; return player1.name < player2.name; } };
Now use the above Function object to sort the list of Player objects using name i.e.
// Sorting List using Function Objects as comparator listofPlayers.sort(PlayerComparator());
Output:
30 :: Angel 2 :: Laura 3 :: Laura 43 :: Riti 22 :: Sid
Sorting a List of Objects with Custom Comparator & Lambda Function
We can also sort a list of Player objects by name using a Lambda function instead of defining a seperate Function object like above.
We can pass a lambda function in sort() as argument. this lambda function will compare two Player objects by name.
// Sorting List using Lambda Function as comparator listofPlayers.sort([](const Player & player1, const Player & player2) { if(player1.name == player2.name) return player1 < player2; return player1.name < player2.name; });
Now sort() will use passed lambda function to compare the Player objects while sorting.
Output:
30 :: Angel 2 :: Laura 3 :: Laura 43 :: Riti 22 :: Sid
Complete example is as follows,
#include <iostream> #include <list> #include <string> #include <algorithm> struct Player { int id; std::string name; Player(int playerId, std::string playerName) : id(playerId), name(playerName) { } bool operator <(const Player & playerObj) const { return id < playerObj.id; } }; struct PlayerComparator { // Compare 2 Player objects using name bool operator ()(const Player & player1, const Player & player2) { if(player1.name == player2.name) return player1 < player2; return player1.name < player2.name; } }; int main() { std::list<Player> listofPlayers = { Player(22, "Sid"), Player(3, "Laura"), Player(43, "Riti"), Player(30, "Angel"), Player(2, "Laura"),}; std::cout<<"****Playes in the list Initially ****"<<std::endl; for(Player & player : listofPlayers) std::cout<<player.id<< " :: "<<player.name<<std::endl; // Sort List by default criteria i.e < operator of Player listofPlayers.sort(); std::cout<<"****After Sorting By ID ****"<<std::endl; for(Player & player : listofPlayers) std::cout<<player.id<< " :: "<<player.name<<std::endl; std::cout<<"****After Sorting By Name ****"<<std::endl; // Sorting List using Lambda function as comparator listofPlayers.sort([](const Player & player1, const Player & player2) { if(player1.name == player2.name) return player1 < player2; return player1.name < player2.name; }); for(Player & player : listofPlayers) std::cout<<player.id<< " :: "<<player.name<<std::endl; std::cout<<"****After Sorting By Name ****"<<std::endl; // Sorting List using Function Objects as comparator listofPlayers.sort(PlayerComparator()); for(Player & player : listofPlayers) std::cout<<player.id<< " :: "<<player.name<<std::endl; return 0; }
Output:
****Playes in the list Initially **** 22 :: Sid 3 :: Laura 43 :: Riti 30 :: Angel 2 :: Laura ****After Sorting By ID **** 2 :: Laura 3 :: Laura 22 :: Sid 30 :: Angel 43 :: Riti ****After Sorting By Name **** 30 :: Angel 2 :: Laura 3 :: Laura 43 :: Riti 22 :: Sid ****After Sorting By Name **** 30 :: Angel 2 :: Laura 3 :: Laura 43 :: Riti 22 :: Sid
To compile the above code in linux use following command,
g++ –std=c++11 example.cpp