37.了解accumulate与for_each

accumulate

有些算法可以帮助我们将一个区间提炼成一个数(或一个对象),诸如count_if,或者min_element和max_element.
但有时候我们需要自定义统计的方式,比如说字符串长度求和,指定区间内乘积之类。stl中存在类似的算法,名为accumulate.值得注意的是,它并不在algorithm中,而是在numeric中。

accumulate的存在形式

标准求和

此形式接受一对迭代器和一个初值:

1
2
list<double> ld; 
double sum = accumulate(ld.begin(), Id.end(), 0.0);

值得注意的是这里初始值是0.0而非0,不然的话accumulate会计算double累加的结果,并将最终结果转为一个int.

另外,accumulate只需要输入迭代器,那也就是说istream_iterator和istreambuf_iterator也可以使用:

1
2
3
cout << "The sum of the ints on the standard input is" 
<< accumulate(istream_iterator<int>(cin), istream_iterator<int>(),0);
//建议迭代器命名,原因详见Effective STL 6

自定义统计(谓词放在最后)

字符串长度求和

为了统计各个字符串长度的和,我们首先写下自定义统计函数:

1
2
3
string::size_type stringLengthSum(string::size_type sumSoFar, const string& s){
return sumSoFar + s.size();
}

对于标准库容器,size_type等价于size_t.
长度求和具体实现如下:
1
2
set<string> ss; 
string::size_type lengthSum =accumulate(ss.begin(), ss.end(), 0, stringLengthSum);

指定区间内的数值乘积

1
2
vector<float> vf; 
float product =accumulate(vf.begin(), vf.end(),1.0f, multiplies<float>());

for_each

for_each是一个对区间内所有元素进行某种操作的算法,我认为配合lambda使用效果绝佳。(需要注意的是它返回的执行操作之后的元素的副本,也许使用引用好一些?)