⬆️ ⬇️

C ++ test case, sorting functor

image

To search for talented programmers wrote a test task C ++. In short, the difficulty of the task is to transfer additional data to the comparison function, which is used by sorting from the standard library.

From Wikipedia:

A functional object (eng. Function object), as well as a functor, functional and functionoid, is a common construction in programming that allows using an object as a function. Often used as a callback, delegate, or as a replacement for lambda expressions in non-functional programming languages.


This test task does not require knowledge of the solution immediately, although an experienced programmer, I think, will easily do so. It is allowed to use the Internet. I could not find a beautiful solution without a hint on stackoverflow . The purpose of the task is to understand whether the applicant is able to read the code, to find solutions to the tasks.





The console program in C ++ consists of a single main.cpp file of 150 lines. Fill the conditional database of employees. There are classes Person (person), Job (place of work), Position (position).



#include <string> struct Person{ Person(); Person(const string& _lastName, const string& _firstName, int _age, int _job_id, int _position_id); string lastName; string firstName; int age; int job_id; int position_id; }; struct Job{ Job(); Job(const string& _name, int _id); string name; int id; }; struct Position{ Position(); Position(const string& _name, int _id); string name; int id; }; 


')

The PersonsList class stores a list of people in std :: vector, and the jobs and positions in the map, which are indexed by id. The Person class refers to Job and Position by their id.



 #include <vector> #include <map> class PersonsList{ public: void addPerson(const Person& person); void addPosition(const Position& position); void addJob(const Job& job); void print(); void sortByName(); void sortByAge(); void sortByJob(); private: std::vector<Person> persons; std::map<int,Job> jobsMap; std::map<int,Position> positionsMap; }; 




The program implements the function of sorting by name using the static comparison function and std :: stable_sort.



 #include <algorithm> bool compareByName(const Person& person1, const Person& person2){ if(person1.lastName==person2.lastName){ return person1.firstName<person2.firstName; } return person1.lastName<person2.lastName; } void PersonsList::sortByName(){ stable_sort(persons.begin(),persons.end(),compareByName); } 




In the main, the database is being filled, the results are sorted and output to the console.

int main ()
 #include <iostream> int main() { PersonsList list; Job google("Google",1); Job microsoft("Microsoft",2); Job hp("Hewlett-Packard",3); list.addJob(google); list.addJob(microsoft); list.addJob(hp); Position junior("Junior developer",1); Position senior("Senior developer",2); Position manager("Manager",3); list.addPosition(junior); list.addPosition(senior); list.addPosition(manager); list.addPerson(Person("Ivanov","Ivan",21,google.id,junior.id)); list.addPerson(Person("Sidorov","Nikolay",28,google.id,senior.id)); list.addPerson(Person("Ivanov","Maxim",28,google.id,manager.id)); list.addPerson(Person("Volkova","Katerina",22,microsoft.id,junior.id)); list.addPerson(Person("Demidov","Vitaly",35,microsoft.id,manager.id)); list.addPerson(Person("Bodrov","Boris",40,hp.id,senior.id)); list.sortByName(); cout<<"Sorted by name:"<<endl; list.print(); cout<<endl; list.sortByAge(); cout<<"Sorted by age:"<<endl; list.print(); cout<<endl; list.sortByJob(); cout<<"Sorted by job:"<<endl; list.print(); return 0; } 






In the source code that I cited above, I missed the implementation of many functions. For those interested, the full source:



Full source
 #include <iostream> #include <iomanip> #include <string> #include <vector> #include <map> #include <algorithm> using namespace std; struct Person{ Person():lastName("noname"),firstName(""),age(0),job_id(0),position_id(0){} Person(const string& _lastName, const string& _firstName, int _age, int _job_id, int _position_id) :lastName(_lastName), firstName(_firstName), age(_age), job_id(_job_id), position_id(_position_id) {} string lastName; string firstName; int age; int job_id; int position_id; }; struct Job{ Job():name("invalid job"),id(-1){} Job(const string& _name, int _id):name(_name),id(_id){} string name; int id; }; struct Position{ Position():name("invalid position"),id(-1){} Position(const string& _name, int _id):name(_name),id(_id){} string name; int id; }; bool compareByName(const Person& person1, const Person& person2){ if(person1.lastName==person2.lastName){ return person1.firstName<person2.firstName; } return person1.lastName<person2.lastName; } class PersonsList{ public: void addPerson(const Person& person){ persons.push_back(person); } void addPosition(const Position& position){ positionsMap[position.id]=position; } void addJob(const Job& job){ jobsMap[job.id]=job; } void print(){ for(int i=0;i<(int)persons.size();i++){ Person& person=persons[i]; Job& job=jobsMap[person.job_id]; Position& position=positionsMap[person.position_id]; cout << setfill (' ') << std::setw (15) << person.lastName; cout << setfill (' ') << std::setw (10) << person.firstName; cout << setfill (' ') << std::setw (5) << person.age << " years"; cout << setfill (' ') << std::setw (20) << job.name; cout << setfill (' ') << std::setw (20) << position.name; cout << endl; } } void sortByName(){ stable_sort(persons.begin(),persons.end(),compareByName); } void sortByAge(){ // ================================================= TODO // programmer also want to change something else, not only this fucntion } void sortByJob(){ // ================================================= TODO } private: std::vector<Person> persons; std::map<int,Job> jobsMap; std::map<int,Position> positionsMap; }; int main() { PersonsList list; Job google("Google",1); Job microsoft("Microsoft",2); Job hp("Hewlett-Packard",3); list.addJob(google); list.addJob(microsoft); list.addJob(hp); Position junior("Junior developer",1); Position senior("Senior developer",2); Position manager("Manager",3); list.addPosition(junior); list.addPosition(senior); list.addPosition(manager); list.addPerson(Person("Ivanov","Ivan",21,google.id,junior.id)); list.addPerson(Person("Sidorov","Nikolay",28,google.id,senior.id)); list.addPerson(Person("Ivanov","Maxim",28,google.id,manager.id)); list.addPerson(Person("Volkova","Katerina",22,microsoft.id,junior.id)); list.addPerson(Person("Demidov","Vitaly",35,microsoft.id,manager.id)); list.addPerson(Person("Bodrov","Boris",40,hp.id,senior.id)); list.sortByName(); cout<<"Sorted by name:"<<endl; list.print(); cout<<endl; list.sortByAge(); cout<<"Sorted by age:"<<endl; list.print(); cout<<endl; list.sortByJob(); cout<<"Sorted by job:"<<endl; list.print(); return 0; } 






The test task is to implement sorting by place of work, and not by id, but by name. The difficulty is that in std :: stable_sort, the third parameter is a function that takes only 2 elements for comparison. Since a pointer to a class is not passed, this function cannot be a class method, but only a static one. Allowed to change the code anywhere.



Solution options are many, and I do not claim to know the optimal solution. Under the spoiler is my solution.

Decision
I used a static comparison function, which takes a third parameter with a pointer to the PersonsList. And to pass this parameter, I wrapped it all in an extra class, which I used as a function.



 bool compareByJobName(const Person& person1, const Person& person2, PersonsList* list){ Job& job1=list->getJobById(person1.job_id); Job& job2=list->getJobById(person2.job_id); return job1<job2; } class sorter { PersonsList* listPointer; public: sorter(PersonsList* _listPointer) : listPointer(_listPointer) {} bool operator()(const Person& person1, const Person& person2) const { return compareByJobName(person1, person2, listPointer ); } }; void PersonsList::sortByJob(){ stable_sort(persons.begin(),persons.end(),sorter(this)); } 


Source: https://habr.com/ru/post/195138/



All Articles