Effective STL学习笔记-条款37
来源:互联网 发布:caffe softmax 参数 编辑:程序博客网 时间:2024/06/03 18:04
用accumulate或for_each来统计区间
一般的统计算法可以使用count和count_if来替代,他们告诉你某个区间有多少等于某个值的元素。
而accumulate和for_each是对于区间的的统计。
accumulate
看个简单例子:
list<double> ld = { 0.0, 0.1, 1.1, 2.2, 3.0 }; double sum = std::accumulate(ld.begin(), ld.end(), 1.1); cout << "sum :" << sum << endl;
这个结果就是sum:7.5,他是从第一个元素1.1开始逐步累加区间的数值
我们还可以按照自己的想法给定一个仿函数实现各种累加:
string::size_type stringLenSum(string::size_type sum, const string& s){ return sum + s.size();} set<string> ss = { "a", "abc" }; string::size_type ssum = accumulate(ss.begin(), ss.end(), 0, stringLenSum); cout << "ssum:" << ssum << endl;
打印结果为4。
让他计算区间的积将更简单,因为我们可以使用标准的multiplies仿函数类:
vector<float> vf = { 1.0f, 1.2f, 2.0f }; float product = accumulate(vf.begin(), vf.end(), 1.0f, multiplies<float>()); cout << "vf : " << product << endl;
计算结果为:2.4f。特别注意计算乘积起始值如果为0,那么结果都是0了。
最后一个晦涩点的例子,他用来寻找point区间的平均值,并且我们也可以看一下accumulate和for_each的区别。
struct Point{ Point(double x_, double y_) :x(x_), y(y_) {}; double x; double y;};//增加一个处理的仿函数,我们可以按照以下方式使用 vector<Point> lp = { { Point(1.0, 2.0) }, { Point(2.0, 4.0) }, { Point(3.0, 6.0)}, }; Point avg = std::accumulate(lp.begin(), lp.end(), Point(0,0), PointAvg()); cout << "Point:" << avg.x << " " << avg.y << endl;
接下来是使用accumulate方式的仿函数实现:
class PointAvg{public: PointAvg():nums(0),xSum(0.0),ySum(0.0){} const Point operator()(const Point& avg, const Point& p) { ++nums; xSum += p.x; ySum += p.y; return Point(xSum / nums, ySum / nums); }private: size_t nums; double xSum; double ySum;};
然而实际上,成员变量的nums,xSum和ySum的存在,可能会造成副作用,技术上讲,以上代码会导致结果未定义。所以for_each出场了。
- 除了副作用问题,for_each和accumulate的不同主要在两个方面。首先,accumulate的名字表示它是一个产生区
间统计的算法,for_each听起来好像你只是要对区间的每个元素进行一些操作,而且,当然,那是那个算法
的主要应用。用for_each来统计一个区间是合法的,但是它没有accumulate清楚。 - 其次,accumulate直接返回那些我们想要的统计值,而for_each返回一个函数对象,我们必须从这个对象中提取想要的统计信息。在C++里,那意味着我们必须给仿函数类添加一个
成员函数
,让我们找回我们追求的统计信息。
class PointAvg{public: PointAvg():nums(0),xSum(0.0),ySum(0.0){} void operator()(const Point& p) { ++nums; xSum += p.x; ySum += p.y; } Point result() const { return Point(xSum / nums, ySum / nums); }private: size_t nums; double xSum; double ySum;}; Point avg2 = std::for_each(lp.begin(), lp.end(), PointAvg()).result(); cout << "Point:" << avg2.x << " " << avg2.y << endl;
就个人来说,我更喜欢用accumulate来统计,因为我认为它最清楚地表达了正在做什么,但是for_each也可
以,而且不像accumulate,副作用的问题并不跟随for_each。两个算法都能用来统计区间。使用最适合你的那
个。
你可能想知道为什么for_each的函数参数允许有副作用,而accumulate不允许。这是一个刺向STL心脏的探针
问题。唉,尊敬的读者,有一些秘密总是在我们的知识范围之外。为什么accumulate和for_each之间有差别?
我尚待听到一个令人信服的解释。 — 原作者。
阅读全文
0 0
- Effective STL学习笔记-条款37
- 【Effective STL】条款1-5学习笔记
- 【Effective STL】条款6-12学习笔记
- 【Effective STL】条款13-18学习笔记
- Effective STL学习笔记-条款1
- Effective STL学习笔记-条款7
- Effective STL学习笔记-条款8-9
- Effective STL学习笔记-条款13|14
- Effective STL学习笔记-条款19
- Effective STL学习笔记-条款20
- Effective STL学习笔记-条款21
- Effective STL学习笔记-条款23
- Effective STL学习笔记-条款24
- Effective STL学习笔记-条款30
- Effective STL学习笔记-条款31
- Effective STL学习笔记-条款32
- Effective STL学习笔记-条款33
- Effective STL学习笔记-条款34
- 想学会刷机就得学会怎么刷小米4S这种手机就能会了
- nagios插件之检测tomcat日志的statusIndex值
- Gym
- EasyUI入门9 EasyUI+NPOI+QrCode实现带二维码复杂格式excel文件导出
- 简单聊聊HTML 5中的Web Storage
- Effective STL学习笔记-条款37
- dns服务
- JAVA | 30
- js对excel数据导入和导出数据
- 数据结构学习-二叉树-链式结构、特殊二叉树、性质、遍历、遍历应用
- 简单聊聊Python中的wraps修饰器
- JS闭包
- HTML-布局-浮动-opacity及支持IE6的写法
- windows中批处理文件