Pull to refresh

Comments 14

Вряд ли такая задача подходит для поиска талантливых программистов. Надо посложнее все таки.
С использованием boost вроде можно так:

void PersonsList::compareByJobName( const Person& person1, const Person& person2 )
{
    Job& job1=getJobById(person1.job_id);
    Job& job2=getJobById(person2.job_id);
    return job1<job2;
}

void PersonsList::sortByJob(){
    stable_sort(persons.begin(),persons.end(), boost::bind(&PersonsList::compareByJobName, this, _1, _2));
}
Спасибо, да, это решение у меня крутилось в голове. boost::bind использую часто, когда линкую сигналы и слоты Wt-шных объектов, код пишу под линуксом, там с бустом просто. Под windows же поднять буст и парвильно настроить — нетривиальная задача, не хотел завязывать на нем этот пример.
bool PersonsList::compareByJobName( const Person& person1, const Person& person2 )
{
    Job& job1=getJobById(person1.job_id);
    Job& job2=getJobById(person2.job_id);
    return job1<job2;
}

void PersonsList::sortByJob(){
    using namespace std::placeholders;
    stable_sort(persons.begin(),persons.end(), std::bind(&PersonsList::compareByJobName, this, _1, _2));
}


Легко, вот пример на чистом C++ без сторонних библиотек :) Даже студия, вроде, уже научилась так делать.
Под windows же поднять буст и парвильно настроить — нетривиальная задача

Да ну, вы что. Для bind и остальной большей части буста, вообще ничего настраивать не нужно, только заинклудить bost/bind.hpp, это же header-only библиотеки.

Что касается link-библиотек, под винду настраивается тривиально. Если не желаете сами собирать, то скачиваете готовые, собранные либы с www.boostpro.com/download/ Там даже msi-установщик готовый.
В C++11 std::bind уже есть. Также можно и лямбдой.
Я конечно не уверен, но, по моему, опыту любой программист работавший с С++ писал когда-то оператор скобок для сортировки. Ну или хотя бы читавший Страуструпа или любую другую книгу не «для чайников».
очень странный пост:
1. в языке и стандартной библиотеке есть — std::bind или лямбда который как раз и предназначены для таких целей;
2. я бы лучше в Person хранил константную ссылку или шаред понинтер на константу на jobs и positions — и возвращал бы значение job и position обычным методом;
3. string firstName;
int job_id;
странный какой-то конвеншн — меня бы насторожило, если бы мне настолько грязный код подсунули на интервью;
4.
bool compareByName(const Person& person1, const Person& person2){
if(person1.lastName==person2.lastName){
return person1.firstName<person2.firstName;
}
return person1.lastName<person2.lastName;
}
для подобного мусора лучше использовать std::tie
return std::tie(person1.lastName, person1.firstName) < std::tie(person2...);

5. compareByName — ф-ция называется compare — хотя возвращает true если меньше. правильно начать название с less.

вообщем не позорьтесь и прячьте пост.
std::bind появился в c++11, также как и std::tie.
Less в названии больше подходит для метода Person::lessByName(const Person& other), когда понятно, кто меньше кого. Также, для строковых переменных слово «сравнить» понятнее, чем «больше» или «меньше».
По поводу ссылок — согласен. Просто это задание я взял из своего опыта, когда я загружал в память данные с SQL Базы для обработки, а там были id поля и ссылки по ним.
По конвеншину — согласен.
Пост пока прятать не буду, спасибо за комментарий.
— я лет 8мь назад ими пользовался только из буста, потом в с++0x, потом в с++11, уже кстати готовиться с++14 так что с++11 — это просто с++.
кстати на интервью до сих пор попадаются кандидаты, которые заявляют я с++ знаю, но stl — нет, хотя стандартная библиотека — это тоже часть языка. теперь также наверное будет и с с++11;
— compare значит сравнить, т.е. результат будет говорить — больше, меньше или равно. в вашем случае — он говорит только меньше.
представьте себе строчку — if (compareByName(...)) — как ее читать английским языком?

>Пост пока прятать не буду, спасибо за комментарий.
это конечно же вам решать. я посоветовал спрятать, что бы вы минусов не нахватались :)
Если не использовать Boost и C++11, решение тоже очень простое — в конструкторе функтора надо передать ссылку на jobsMap. Такой подход постоянно практикуется у Скотта Маерса в Effective STL.
Я набросал решение, но не стал проверять валидность job_id. Надо конечно делать через find, а не через operator[].
На всякий случай решение в статье я не смотрел :-))

class CompareByJobName: public std::binary_function<Person, Person, bool>{
	std::map<int, Job> &jobsMap;
	public:
	CompareByJobName(std::map<int, Job> &_jobsMap): jobMap(_jobMap){};
	inline bool operator()(const Person& person1, const Person& person2){
		if(person1.job_id==person2.job_id){
			if(person1.lastName==person2.lastName){
				return person1.firstName<person2.firstName;
			}else return    person1.lastName<person2.lastName;
		}
		return jobsMap[person1.job_id] < jobsMap[person2.job_id] ;
	}
}

std::stable_sort(persons.begin(),persons.end(),CompareByJobName(jobsMap) );
Особоенность stable_sort как раз в том, что он не меняет порядок элементов, которые равны по ключу сортировки.
Если я отсортировал по имени, а затем по месту работы, то в пределах одной работы останется сортировка по имени.
Если я не ошибась, стандартная библиотека использует merge sort для стабильной сортировки. Если же использовать std::sort, то используется merge sort для структур, и quick sort (не стабильный, но быстрее) для простых типов.
Sign up to leave a comment.

Articles