Lambda表达式的使用以及相应类的等价替换方法
Lambda表达式结构:
auto f = [ 捕获列表 ] ( 操作参数列表 ) { 操作函数体 };
其中 捕获列表和函数体的括号标记不能省略
引子 从operator()说起:
1.1 operate()实现将对象当函数使用
案例1 内含operate()重载
#include <iostream>
using namespace std;
class FUN {
public:
double operator()(double x)const {
return x*x;
}
int operator()(int a, int b, int c = 9) {
return a + b - c;
}
};
int main() {
FUN fun;
cout << fun(12.) << endl; //144.0
cout << fun(10, 20, 30) << endl; //0
cout << fun(10, 20) << endl; // 21
return 0;
}
变体 Lambda表达式的公共类改写
2.1 案例1 vector排序
使用Lambda表达式的vector排序
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
vector<int> numbers = {7, 1, 3, 4, 2};
sort(numbers.begin(), numbers.end(),
[](int a, int b){return a < b;});
}
将Lambda表达式改为operate()类的对象当函数
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
struct FUN {
bool operator()(int a, int b)const {
return a < b;
}
};
int main() {
vector<int> numbers = {7, 1, 3, 4, 2};
sort(numbers.begin(), numbers.end(), FUN{});
}
2.2 案例2 vector取交集
2.2.1 直接使用Lambda表达式
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
vector<int> xs = {7, 1, 3, 4, 2};
vector<int> ys = {8, 2, 4, 5, 3};
auto count = count_if(xs.begin(), xs.end(),[&ys](int x){
return find(ys.begin(), ys.end(), x) != ys.end();
});
cout << count << endl;
}
p.s.:
count_if(a.begin(), a.end(), fun)
: 返回满足fun
条件的a
中元素的数目
2.2.2 将Lambda表达式改为operate()类的对象当函数
(捕获列表将作为struct的私有成员变量)
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
struct FUNS {
private:
vector<int>& ys;
public:
FUNS(vector<int>& theYs) : ys(theYs) {}
bool operator()(int x)const {
return find(ys.begin(), ys.end(), x) != ys.end();
}
};
int main() {
vector<int> xs = {7, 1, 3, 4, 2};
vector<int> ys = {8, 2, 4, 5, 3};
auto count = count_if(xs.begin(), xs.end(), FUNS{ys});
// 类直接作为函数进行操作,捕获列表的参数转化成相应功能类的私有成员变量
cout << count << endl;
}
2.2.3 使用function处理捕获列表为右值的处理办法
解决捕获列表中出现右值引用的情况, 捕获列表改为变量 var = move(右值引用)
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
function<bool(int)> Pred(vector<int>&& ys) {
// 捕获函数等号两边变量可以同名(代码生成后并不在嵌套的作用域中)
return [ys = move(ys)](int x){
return find(ys.begin(), ys.end(), x) != ys.end();
};
}
int main() {
vector<int> xs = {7, 1, 3, 4, 2};
auto count = count_if(xs.begin(), xs.end(), Pred({8, 2, 4, 5, 3}));
cout << count << endl;
}
2.2.4 定义操作类进一步细化处理右值引用的function操作
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
using namespace std;
struct FUNS {
private:
vector<int> ys;
public:
FUNS(vector<int>& theYs) : ys{move(theYs)}{}
bool operator()(int x)const {
return find(ys.begin(), ys.end(), x) != ys.end();
}
};
function<bool(int)> Pred(vector<int>&& ys) {
return FUNS{ys};
}
int main() {
vector<int> xs = {7, 1, 3, 4, 2};
auto count = count_if(xs.begin(), xs.end(), Pred({8, 2, 4, 5, 3}));
cout << count << endl;
}
Lambda表达式既不能使用值, 也不能使用引用来捕获自己,一定要使用function
Lambda表达式不能捕获用auto定义的变量
总结 Lambda表达式与struct类之间的转换关系
[捕获列表中的变量] —>类的私有成员, 也参与类中复制构造函数的创建
(参数列表) —>类中operator()的参数列表
{函数体} —>类中operator()的函数体
典例
Leetcode1030 按曼哈顿距离对矩阵单元格坐标进行顺序排列
给出 R 行 C 列的矩阵,其中的单元格的整数坐标为 (r, c),满足 0 <= r < R 且 0 <= c < C。
另外,我们在该矩阵中给出了一个坐标为 (r0, c0) 的单元格。
返回矩阵中的所有单元格的坐标,并按到 (r0, c0) 的距离从最小到最大的顺序排,其中,两单元格(r1, c1) 和 (r2, c2) 之间的距离是曼哈顿距离,|r1 - r2| + |c1 - c2|。(你可以按任何满足此条件的顺序返回答案。)
输入:R = 2, C = 3, r0 = 1, c0 = 2
输出:[[1,2],[0,2],[1,1],[0,1],[1,0],[0,0]]
解释:从 (r0, c0) 到其他单元格的距离为:[0,1,1,2,2,3]
其他满足题目要求的答案也会被视为正确,例如 [[1,2],[1,1],[0,2],[1,0],[0,1],[0,0]]。
class Solution {
public:
vector<vector<int>> allCellsDistOrder(int R, int C, int r0, int c0) {
vector<vector<int>> ans(R * C, vector<int>(2));
for (int i = 0; i < R; i++) {
for (int j = 0; j < C; j++) {
ans[i * C + j][0] = i;
ans[i * C + j][1] = j;
}
}
sort(ans.begin(), ans.end(), [r0, c0](vector<int> a, vector<int> b){
if ((abs(r0-a[0]) + abs(c0-a[1])) < (abs(r0-b[0]) + abs(c0-b[1]))) {
return true;
}
return false;
});
return ans;
}
};