如何使用list :: sort排序对象列表?

时间:2018-12-09 07:00:34

标签: c++ list sorting lambda

我不得不根据加班时间订购一份工人名单,所以第一个是加班时间更多的工人。我之前问过这个问题,答案是将这个函数与lambda一起使用:

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

    }
};

它可以正常工作,但是即使在网上阅读了有关lambda的信息后,我还是不太了解。除了使用列表的排序算法或任何其他方法之外,有没有办法做同样的事情?

5 个答案:

答案 0 :(得分:4)

  

它可以正常工作,但是即使在网上阅读了有关lambda的信息后,我还是不太了解。除了使用列表的排序算法或任何其他方法之外,有没有办法做同样的事情?

您正在使用sort的{​​{1}}成员函数。 std::list::sort有两个重载。

std::list

在您的情况下,您正在使用第二个重载。它允许自定义比较功能对列表中的项目进行排序。使用void sort(); template< class Compare > void sort( Compare comp ); 函数是提供自定义比较函数的一种方法。您可以使用其他方式提供自定义比较功能,例如:

  1. 非成员函数。

    lambda

    并将其用作:

    bool compareWorkers(Worker const& lh, Worker const& rh)
    {
       return (lh.Overtimehours() > rh.Overtimehours());
    }
    
  2. workers_Copy.sort(compareWorkers); 中的一个static成员函数。

    Workers

    并将其用作:

    static bool compare(Worker const& lh, Worker const& rh)
    {
       return (lh.Overtimehours() > rh.Overtimehours());
    }
    
  3. 函子类。

    workers_Copy.sort(Workers::compare);
    

    并将其用作:

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

答案 1 :(得分:0)

不需要lambda只需传递一个比较函数即可。

  code = form.code.data
  qr = pyqrcode.create(code)
  qr.png(code+'.png', scale=6)
  with open(code+'.png', "rb") as f:
    return Response(f.read(), content_type="image/png")

或不是一个好方法,因为它会使任何程序员感到困惑,在worker类中声明operator <,因为没有人会期望这个操作员会在加班时进行比较。

诚实地使用lambda版本。

答案 2 :(得分:0)

Lambda是匿名函数。因此,如果您对lambda不满意,则可以根据条件创建一个比较函数。然后只需将该函数作为参数传递给sort函数即可。

答案 3 :(得分:0)

实际上,您要做的就是使用lambda在调用sort()的内部构造函数对象。在cpp参考(http://www.cplusplus.com/reference/list/list/sort/)上显示了使用先前声明和定义的函数的方法。

因此,您已经在使用list的sort方法,您只是在告诉它要使用哪个方法来确定哪个对象比另一个对象小。您无需使用lambda即可实现相同的目的。

这未经测试,但是应该使用声明的命名方法而不是lambda来等效。

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

}

答案 4 :(得分:0)

没有lambda:

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

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

Lambda是一种生成本地函数的便捷方法,否则您将不得不明确定义这些本地函数,通常是在实际需要它们的一定距离处。

实际上,这有点短,lambda更像一个函子,但是如果它们确实具有空捕获,则可以隐式(或显式)转换为函数指针。试图完整地解释它们将超出此答案的范围,您应该获得一本不错的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再次获得右值(没有该值将不再存在)。