Как заказать список объектов используя list :: sort? - PullRequest
0 голосов
/ 09 декабря 2018

Мне пришлось заказать список работников, исходя из их сверхурочных часов, поэтому первым должен был стать тот, кто работал сверхурочно.Я спрашивал об этом раньше, и я получил ответ об использовании этой функции с лямбда-выражениями:

class Workers {
private:
    list<Worker> workers;
public:
    Workers() {
    }
    Workers(list<Worker> workers) {
        this->workers = workers;
    }
    void OvertimeHoursReport() {
        list<Worker> workers_Copy;
        workers_Copy = workers;
        workers_Copy.sort([](Worker& lh, Worker& rh) { return lh.Overtimehours() > rh.Overtimehours(); });
        for (list<Worker>::iterator it = workers_Copy.begin(); it != workers_Copy.end(); it++) {
            if ((it)->Overtimehours() > 0) {
                cout << "Name:";
                cout<<(it)->getName();
                cout << ' ';
                cout<<(it)->getLastname();
                cout << ' '<<"Sex: ";
                if ((it)->getSex() == true) {
                    cout << "Male" << ' ';
                }
                if ((it)->getSexo() == false) {
                    cout << "female" << ' ';
                }
                cout << "Overtime Hours: ";
                cout<<(it)->Overtimehours();
                cout << endl;
            }
        }

    }
};

Она отлично работает, но я не очень понимаю, как работают лямбды, даже после прочтения о них в Интернете.Есть ли способ сделать то же самое, но с помощью алгоритма сортировки списка или любого другого метода?

Ответы [ 5 ]

0 голосов
/ 09 декабря 2018

Без лямбды:

bool isLess(Worker& lh, Worker& rh) { /* ... */ }

class Workers
{
    void OvertimeHoursReport()
    {
        list<Worker> workers_Copy(workers);
        workers_Copy.sort(isLess);
        // ...
    }
};

Лямбды - это удобный способ создания локальных функций, которые в противном случае вам пришлось бы определять явно, обычно на таком расстоянии, на котором они действительно нужны.

На самом деле, это немного короче, лямбды больше похожи на функторы, но могут быть преобразованы в указатель на функцию неявно (или явно) , если они имеют пустой захват.Попытка объяснить их полностью вышла бы за рамки этого ответа, вы должны получить хорошую книгу по C ++.

Одна вещь о вашем конструкторе:

Workers(list<Worker> workers) // creates an intermediate _copy_(!) of parameter
// this->workers is initialized as empty here
{
    this->workers = workers; // now you assign by copying again!
}

Вы можете сэкономить копию, есливместо этого вы используете ссылку;Вы можете инициализировать член напрямую (за исключением пустой инициализации), если используете список инициализаторов классов (не путать с std::initializer_list):

Workers(list<Worker> const& workers) // reference, no copy
    : workers(workers) // direct initialization
{ }

Вариант:

Workers(list<Worker> workers) // the copy again!
    : workers(std::move(workers)) // now you move your copy into member
{ }

Этот вариант можно использовать для создания копии, но также можно переместить внешний список в:

Workers(someList); // copy!
Workers(std::move(someList)); // uses move constructor
                              // -> moves someList into temporary, from
                              // which it is moved again to member

Вы можете полностью избежать промежуточного элемента, но тогда вам понадобятся два конструктора для:

Workers(list<Worker> const& workers); // reference, as before, copies
Workers(list<Worker>&& workers)       // rvalue reference!
    : workers(std::move(workers))     // move!
{ }

Примечание: std::move гарантирует, что параметр worker снова получит значение r (без которого больше не будет).

0 голосов
/ 09 декабря 2018

На самом деле все, что вы делаете, - это использование вашей лямбды для создания вашего функционального объекта на месте внутри вызова метода sort ().Метод, использующий функцию, объявленную и определенную ранее, показан в ссылке на cpp (http://www.cplusplus.com/reference/list/list/sort/).

. Таким образом, вы уже используете метод сортировки списка, вы просто указываете, какой метод использовать, чтобы определить, какойОбъект меньше другого. Вы можете достичь того же самого, не используя лямбду.

Это не проверено, но должно быть эквивалентно использованию объявленного именованного метода вместо лямбды.

bool CompareHours(Worker& lh, Worker& rh) { return lh.Overtimehours() > rh.Overtimehours(); }
void OvertimeHoursReport() {
    list<Worker> workers_Copy;
    workers_Copy = workers;
    workers_Copy.sort(CompareHours);
    for (list<Worker>::iterator it = workers_Copy.begin(); it != workers_Copy.end(); it++) {
        if ((it)->Overtimehours() > 0) {
            cout << "Name:";
            cout<<(it)->getName();
            cout << ' ';
            cout<<(it)->getLastname();
            cout << ' '<<"Sex: ";
            if ((it)->getSex() == true) {
                cout << "Male" << ' ';
            }
            if ((it)->getSexo() == false) {
                cout << "female" << ' ';
            }
            cout << "Overtime Hours: ";
            cout<<(it)->Overtimehours();
            cout << endl;
        }
    }

}
0 голосов
/ 09 декабря 2018

нет необходимости в лямбде, просто передайте функцию сравнения.

bool compareByOvertime(const Worker& lh,const Worker& rh)
{
    return lh.Overtimehours() > rh.Overtimehours();
};

или не очень хороший способ, потому что это запутает любого программиста, объявите operator <в рабочем классе, потому что никто не будет ожидать этот операторсравнивать сверхурочно.</p>

Честно придерживайтесь лямбда-версии.

0 голосов
/ 09 декабря 2018

Лямбды - это анонимные функции.Поэтому, если вам не нравятся лямбды, вы можете создать функцию для сравнения на основе ваших критериев.Затем просто передайте эту функцию в качестве аргумента функции сортировки.

0 голосов
/ 09 декабря 2018

Работает отлично, но я не очень понимаю, как работают лямбды, даже прочитав о них в Интернете.Есть ли способ сделать то же самое, но с помощью алгоритма сортировки списка или любого другого метода?

Вы используете sort функцию-член std::list.Существует две перегрузки: std::list::sort.

void sort();
template< class Compare >
void sort( Compare comp );

В вашем случае вы используете вторую перегрузку.Это позволяет настраивать функции сравнения для сортировки элементов в списке.Использование функции lambda является одним из способов предоставления пользовательской функции сравнения.Вы можете использовать другие способы предоставления пользовательской функции сравнения, такие как:

  1. Не являющаяся членом функция.

    bool compareWorkers(Worker const& lh, Worker const& rh)
    {
       return (lh.Overtimehours() > rh.Overtimehours());
    }
    

    и использовать ее как:

    workers_Copy.sort(compareWorkers);
    
  2. A static член функции в Workers.

    static bool compare(Worker const& lh, Worker const& rh)
    {
       return (lh.Overtimehours() > rh.Overtimehours());
    }
    

    и использовать его как:

    workers_Copy.sort(Workers::compare);
    
  3. Класс функтора.

    struct CompareWorkers
    {
       bool operator()(Worker const& lh, Worker const& rh) const
       {
          return (lh.Overtimehours() > rh.Overtimehours());
       }
    };
    

    и использовать его как:

    workers_Copy.sort(CompareWorkers());
    
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...