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

版权声明:本文为Maushawkin原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。