テストC ++、並べ替えのファンクター

画像

優秀なプログラマーを探すために、彼はC ++テストタスクを作成しました。 つまり、タスクの複雑さは、追加のデータを比較関数に転送することです。比較関数は、標準ライブラリからのソートで使用されます。

ウィキペディアから:

関数オブジェクト(英語の関数オブジェクト)、ファンクタ、関数型および関数型は、プログラミングで一般的な構造であり、オブジェクトを関数として使用できます。 多くの場合、コールバック、デリゲート、または非機能プログラミング言語のラムダ式の代替として使用されます。


このテストタスクでは、すぐにソリューションの知識は必要ありませんが、経験豊富なプログラマは簡単にそれを行うことができます。 インターネットの使用を許可。 私はstackoverflowのヒントなしで美しい解決策を見つけることができませんでした。 タスクの目的は、申請者がコードを読み、タスクの解決策を見つけることができるかどうかを理解することです。





C ++コンソールプログラムは、150行のmain.cppファイルで構成されています。 従業員の条件付きデータベースに入力します。 クラスには、人(人)、仕事(職場)、役職(役職)があります。



#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; };
      
      







PersonsListクラスは、std :: vectorの人々のリスト、およびidでインデックス付けされたマップ内の作業場所と位置を格納します。 Personクラスは、IDによってJobとPositionを参照します。



 #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; };
      
      







プログラムは、静的比較関数と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); }
      
      







主なものは、データベースへの入力、ソート、およびコンソールへの結果の出力です。

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; }
      
      









上記で引用したソースコードでは、多くの機能の実装を逃していました。 興味がある人のために、完全なソース:



完全なソース
 #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; }
      
      









テストタスクは、IDではなく名前で作業場所による並べ替えを実装することです。 困難な点は、std :: stable_sortでは、3番目のパラメーターが比較のために2つの要素のみを取る関数であることです。 クラスへのポインタが渡されないため、この関数はクラスメソッドではなく、静的メソッドになります。 コードはどこでも変更できます。



多くの解決策がありますが、最適な解決策を知っているふりはしません。 ネタバレの下で、私の解決策。

解決策
3番目のパラメーターとしてPersonsListへのポインターを受け取る静的比較関数を使用しました。 そして、このパラメーターを渡すために、関数として使用した追加のクラスですべてをラップしました。



 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)); }
      
      








All Articles