如何使用 lambda 进行排序?

199
sort(mMyClassVector.begin(), mMyClassVector.end(), 
    [](const MyClass & a, const MyClass & b)
{ 
    return a.mProperty > b.mProperty; 
});

我想使用lambda函数来排序自定义类,而不是绑定实例方法。然而,上面的代码会产生以下错误:
error C2564: 'const char *' : a function-style conversion to a built-in type can only take one argument
使用boost::bind(&MyApp::myMethod, this, _1, _2)可以正常工作。

该向量是一个包含整数和两个字符串的结构体。这里的属性将是一个整数。 - BTR
5
请给我们展示一个小的可编译示例。 - GManNickG
4个回答

235
明白了。
升序:
std::ranges::sort(mMyClassVector, [](const MyClass &a, const MyClass &b)
{ 
    return a.mProperty < b.mProperty; 
});

下降:

std::ranges::sort(mMyClassVector, [](const MyClass &a, const MyClass &b)
{ 
    return a.mProperty > b.mProperty; 
});

当使用比C++20更旧的标准时,你可以使用std::sort(mMyClassVector.begin(), mMyClassVector.end(), ...)代替。

2
你目前所写的内容意义不大。如果mProperty应该是一个int类型,那么a.mProperty>b.mProperty肯定会产生一个bool类型的结果。 - sellibitze
11
应该是operator<,而不是operator>吧? - Warpspace
14
应该使用“<”符号表示标准升序。我编辑了答案以明确它是降序排序,但显然我的编辑没有起到帮助作用,被删除了! - pancake
3
我刚在GCC 5.3.0中尝试了一下,-> bool部分是不必要的。 - David Grayson
5
由于 VC(Visual C++) 的一个 bug,明确指定返回类型是必需的,这是高度可能发生的情况。请注意,此处涉及技术术语和缩写,因此翻译可能需要根据上下文进行一些调整。 - Conrad Jones
显示剩余4条评论

37
您可以像这样使用它:
#include<array>
#include<functional>
using namespace std;
int main()
{
    array<int, 10> arr = { 1,2,3,4,5,6,7,8,9 };

    sort(begin(arr), 
         end(arr), 
         [](int a, int b) {return a > b; });

    for (auto item : arr)
      cout << item << " ";

    return 0;
}

6
问题可能出在"a.mProperty > b.mProperty"这行代码上吗?我已经使以下代码正常工作:
#include <algorithm>
#include <vector>
#include <iterator>
#include <iostream>
#include <sstream>

struct Foo
{
    Foo() : _i(0) {};

    int _i;

    friend std::ostream& operator<<(std::ostream& os, const Foo& f)
    {
        os << f._i;
        return os;
    };
};

typedef std::vector<Foo> VectorT;

std::string toString(const VectorT& v)
{
    std::stringstream ss;
    std::copy(v.begin(), v.end(), std::ostream_iterator<Foo>(ss, ", "));
    return ss.str();
};

int main()
{

    VectorT v(10);
    std::for_each(v.begin(), v.end(),
            [](Foo& f)
            {
                f._i = rand() % 100;
            });

    std::cout << "before sort: " << toString(v) << "\n";

    sort(v.begin(), v.end(),
            [](const Foo& a, const Foo& b)
            {
                return a._i > b._i;
            });

    std::cout << "after sort:  " << toString(v) << "\n";
    return 1;
};

输出结果为:
before sort: 83, 86, 77, 15, 93, 35, 86, 92, 49, 21,
after sort:  93, 92, 86, 86, 83, 77, 49, 35, 21, 15,

是的,我使用的设置出现了问题。在我的笔记本电脑上编译没有问题,但在 Visual Studio 2010 的团队版中有问题。它提示我切换回 bind 然后错误就消失了。我当时使用的是 VC10 Express。这是个Bug吗? - BTR
让代码更加简洁,这就是为什么 OP 想要使用 Lambda 的原因。 - user7111260

3
您可以这样对数组进行排序:
#include <bits/stdc++.h>
using namespace std;
int main() {
    int q[] = {1, 3, 5, 7, 9, 2, 4, 6, 8 ,10};
    sort(q, q + 10, [&](int A, int B) { return A < B; });
    for (int i = 0; i < 10; i++)
        cout << q[i] << ' ';
    return 0;
}

before sort: 1 3 5 7 9 2 4 6 8 10
after sort: 1 2 3 4 5 6 7 8 9 10 

我总是喜欢在ACM竞赛中使用lambda表达式来对结构体数组进行排序,就像这样:

struct item {
    int a, b;
};

vector<item> q;

sort(q.begin(), q.end(), [&](item t1, item t2) {
    return t1.a < t2.a;
});


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接