C++使用技巧(二十六):unique、distance、accumulate搭配lambda函数表达式使用

1、方法介绍与使用

C++ 11 引入了 lambda 表达式,以允许我们编写一个内联函数,该函数可用于无法重用且不值得命名的短代码片段。最简单的 lambda 表达式可以定义如下:

[ capture clause ] (parameters) -> return-type  
{   
   definition of method   
} 

通常 lambda 表达式中的 return-type 由编译器本身评估,我们不需要显式指定和 -> return-type 部分可以忽略,但在一些复杂的情况下,如条件语句,编译器无法确定返回类型,我们需要指定。

1 capture list 

是一个lambda所在函数中定义的局部变量的列表,通常为空;

2 return type

返回值类型;

可忽略,使用自动推倒;

尾置返回类型;就是用    ->后面跟类型    来表示函数的返回类型,这样更直观;

3 parameter list

参数列表;

可忽略,自动推倒;

4 function body

函数体;

其中carpture是捕获列表,params是参数,opt是选项,ret则是返回值的类型,body则是函数的具体实现。

补充说明:

[ capture ] ( params ) opt -> ret { body; };

1.捕获列表描述了lambda表达式可以访问上下文中的哪些变量。
[] :表示不捕获任何变量
[=]:表示按值捕获变量
[&]:表示按引用捕获变量
[this]:值传递捕获当前的this
但是捕获列表不允许变量的重复传递:例如
[=,x]
上面这种捕获是不允许的,=表示按值的方式捕获所有的变量,x相当于被重复捕获了。
2.params表示lambda的参数,用在{}中。
3.opt表示lambda的选项,例如mutable,后面会介绍一下mutable的用法。
4.ret表示lambda的返回值,也可以显示指明返回值,lambda会自动推断返回值,
但是值得注意的是只有当lambda的表达式仅有一条return语句时,自动推断才是有效的。

参考来源:https://blog.csdn.net/weixin_43055404/article/details/103299156

案例1:

#include <iostream>
using namespace std;
int main()
{
	int a = 5,b = 6;
	auto f = [=]{return a+b;};//[=]按值捕获了a和b
	cout << f() << endl;
	return 0;
}

运行程序输出结果为11,由上栗看出可以给lambda指定一个名称,再用该名称来取代调用该表达式。

案例2:

#include <iostream>
using namespace std;
int main()
{
	int a = 5;
	auto f1 = [=]{return a+1;};//按值捕获a
	auto f2 = [&]{return a+1;};//按引用捕获a
	cout << f1() << endl;
	cout << f2()<< endl;
	a++;
	cout << f1() << endl;
	cout << f2() << endl;
	return 0;
}

结果:
6
6
6
7

2、demo应用

下面给出了具有标准函数的 lambda 表达式的各种用法:

// C++ program to demonstrate lambda expression in C++
#include <bits/stdc++.h>
using namespace std;

// Function to print vector
void printVector(vector<int> v)
{
	// lambda expression to print vector
	for_each(v.begin(), v.end(), [](int i)
	{
		std::cout << i << " ";
	});
	cout << endl;
}

int main()
{
	vector<int> v {4, 1, 3, 7, 2, 3, 1, 17};

	printVector(v);

	// below snippet find first number greater than 4
	// find_if searches for an element for which
	// function(third argument) returns true
	vector<int>:: iterator p = find_if(v.begin(), v.end(), [](int i){return i > 4;});
    //寻找满足以下条件的元素  第一个元素就是输出
	cout << "First number greater than 4 is : " << *p << endl;


	// function to sort vector, lambda expression is for sorting in
	// non-increasing order Compiler can make out return type as
	// bool, but shown here just for explanation
	sort(v.begin(), v.end(), [](const int& a, const int& b) -> bool
	{
		return a > b;//倒顺序 
	});

	printVector(v);

	// function to count numbers greater than or equal to 5
	int count_5 = count_if(v.begin(), v.end(), [](int a)
	{
		return (a >= 5);
	});
	cout << "The number of elements greater than or equal to 5 is : "
		<< count_5 << endl;

	// function for removing duplicate element (after sorting all
	// duplicate comes together)
	p = unique(v.begin(), v.end(), [](int a, int b)
	{
		return a == b;
	});
    
    // printVector(v);
    cout << "去掉重复的数 : "<<endl;

	// resizing vector to make size equal to total different number
	v.resize(distance(v.begin(), p)); //计算去掉后的数组的元素个数,并重新排列大小
	printVector(v);

	// accumulate function accumulate the container on the basis of
	// function provided as third argument
	int arr[] = {1, 2, 3, 4, 5};
	int f = accumulate(arr, arr + 5, 1, [](int i, int j){return i * j;});

	cout << "Factorial of 5 is : " << f << endl;// 将数组的元素相乘,这里类似阶乘计算,如果数字没有顺序就是正常的元素相乘

	//	 We can also access function by storing this into variable
	auto square = [](int i)
	{
		return i * i;
	};

	cout << "Square of 5 is : " << square(5) << endl;
}

执行结果:

4 1 3 7 2 3 1 17 
First number greater than 4 is : 7
17 7 4 3 3 2 1 1 
The number of elements greater than or equal to 5 is : 2
去掉重复的数 : 
17 7 4 3 2 1 
Factorial of 5 is : 720
Square of 5 is : 25

其中:用到的函数
unique的作用是从输入序列中“删除”所有相邻的重复元素。
distance() 函数用于计算两个迭代器表示的范围内包含元素的个数.
accumulate带有三个形参:头两个形参指定要累加的元素范围,第三个形参则是累加的初值。accumulate函数将它的一个内部变量设置为指定的初始值,然后在此初值上累加输入范围内所有元素的值。accumulate算法返回累加的结果,其返回类型就是其第三个实参的类型。

这里补充accumulate案例用法:

#include <vector>
#include <numeric>
#include <functional>
#include <iostream>

using namespace std;

int main( ) 
{

   vector <int> v1, v2( 20 );
   vector <int>::iterator Iter1, Iter2;

   int i;
   for ( i = 1 ; i < 21 ; i++ )
   {
      v1.push_back( i );//给向量数组 赋值
   }

   cout << "最初向量v1中个元素的值为:\n ( " ;
   for ( Iter1 = v1.begin( ) ; Iter1 != v1.end( ) ; Iter1++ )
      cout << *Iter1 << " ";
   cout << ")." << endl;

   // accumulate函数的第一个功能,求和
   int total;
   total = accumulate ( v1.begin ( ) , v1.end ( ) , 0 );

   cout << "整数从1到20的和为: " 
        << total << "." << endl;

   // 构造一个前n项和的向量
   int j = 0, partotal;
   for ( Iter1 = v1.begin( ) + 1; Iter1 != v1.end( ) + 1 ; Iter1++ )
   {
      partotal = accumulate ( v1.begin ( ) , Iter1 , 0 );
      v2 [ j ] = partotal;
      j++;
   }

   cout << "前n项和分别为:\n ( " ;
   for ( Iter2 = v2.begin( ) ; Iter2 != v2.end( ) ; Iter2++ )
      cout << *Iter2 << " ";
   cout << ")." << endl << endl;

   // accumulate函数的第二个功能,计算连乘积
   vector <int> v3, v4( 10 );
   vector <int>::iterator Iter3, Iter4;

   int s;
   for ( s = 1 ; s < 11 ; s++ )
   {
      v3.push_back( s );
   }

   cout << "向量v3的初始值分别为:\n ( " ;
   for ( Iter3 = v3.begin( ) ; Iter3 != v3.end( ) ; Iter3++ )
      cout << *Iter3 << " ";
   cout << ")." << endl;

    //相乘,没有遍历
   int ptotal;
   ptotal = accumulate ( v3.begin ( ) , v3.end ( ) , 1 , multiplies<int>( ) );

   cout << "整数1到10的连乘积为: " 
        << ptotal << "." << endl;

   // 构造一个前n项积的向量 相乘,开始遍历
   int k = 0, ppartotal;
   for ( Iter3 = v3.begin( ) + 1; Iter3 != v3.end( ) + 1 ; Iter3++ ) {
      ppartotal = accumulate ( v3.begin ( ) , Iter3 , 1 , multiplies<int>( ) );
      v4 [ k ] = ppartotal;
      k++;
   }

   cout << "前n项积分别为:\n ( " ;
   for ( Iter4 = v4.begin( ) ; Iter4 != v4.end( ) ; Iter4++ )
      cout << *Iter4 << " ";
   cout << ")." << endl;
}

执行结果:

最初向量v1中个元素的值为:
 ( 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ).
整数从120的和为: 210.
前n项和分别为:
 ( 1 3 6 10 15 21 28 36 45 55 66 78 91 105 120 136 153 171 190 210 ).

向量v3的初始值分别为:
 ( 1 2 3 4 5 6 7 8 9 10 ).
整数110的连乘积为: 3628800.
前n项积分别为:
 ( 1 2 6 24 120 720 5040 40320 362880 3628800 ).

补充:continue语句 可以使用该语句应用与上面的方法中
作用:
循环语句中,跳过本次循环中余下尚未执行的语句,继续执行下一次循环

#include <iostream>
using namespace std;

int main() {

	for (int i = 0; i < 20; i++)
	{
		if (i % 2 == 0)
		{
			continue; 
            //如果条件为真则继续循环,否则将值传递给吓一语句i
		}
		cout << i << endl;
	}
	
	// system("pause");

	return 0;
}


执行结果:

1
3
5
7
9
11
13
15
17
19

参考

http://www.noobyard.com/article/p-gxpewbej-n.html
https://www.oracle.com/cn/servers/technologies/howto-use-lambda-exp-cpp11.html

https://blog.csdn.net/weixin_43055404/article/details/103299156

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

源代码杀手

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值