在同一输入迭代器范围内并排运行两个 <algorithm>
Posted
技术标签:
【中文标题】在同一输入迭代器范围内并排运行两个 <algorithm>【英文标题】:Run two <algorithm>s side by side on the same input iterator range 【发布时间】:2013-12-10 18:51:58 【问题描述】:如果我想计算从std::istream
检索到的一堆数字的总和,我可以执行以下操作:
// std::istream & is = ...
int total = std::accumulate(std::istream_iterator<int>(is),
std::istream_iterator<int>(),
0);
但是,如果我想计算它们的平均值,我需要累积两个不同的结果:
总和 (std::accumulate
)
总计数 (std::distance
)
有没有办法“合并”这两种算法并在迭代器范围的单次传递中“并排”运行它们?我想做类似的事情:
using std::placeholders;
int total, count;
std::tie(total, count) = merge_somehow(std::istream_iterator<int>(is),
std::istream_iterator<int>(),
std::bind(std::accumulate, _1, _2, 0),
std::distance);
double average = (double)total / count;
这可能吗?
【问题讨论】:
【参考方案1】:Boost.Accumulators 实现了这种单程累积的现成解决方案。您制作一个累加器,例如求和、计数和平均,填充它,然后在最后提取所有三个结果。
【讨论】:
【参考方案2】:您不能合并两个不同的算法以进行交错。算法控制流程,您只能拥有一个流程。现在,在您的特定情况下,您可以模拟它:
int count = 0;
int total = std::accumulate(std::istream_iterator<int>(is),
std::istream_iterator<int>(),
0,
[&](int x, int y) ++count; return x+y; );
【讨论】:
【参考方案3】:这完全是 hack,但是是这样的:
#include <iostream>
#include <algorithm>
#include <tuple>
#include <iterator>
#include <sstream>
namespace Custom
template <class InputIterator, class T, class Bind, typename... Args>
std::tuple<Args...> accumulate (InputIterator first, InputIterator last,
T init, T& output, Bind bind, Args&... args)
while (first!=last)
init = bind(init, *first, args...);
++first;
output = init;
std::tuple<Args...> tuple(args...);
return tuple;
int main()
int total = 0, count = 0;
std::istringstream is;
is.str("1 2 3 4 5");
std::tie(count) = Custom::accumulate(std::istream_iterator<int>(is),
std::istream_iterator<int>(),
0,
total,
std::bind([&] (int a, int b, int& count) ++count; return a + b; ,
std::placeholders::_1, std::placeholders::_2, std::placeholders::_3),
count);
std::cout << total << " " << count;
return 0;
【讨论】:
以上是关于在同一输入迭代器范围内并排运行两个 <algorithm>的主要内容,如果未能解决你的问题,请参考以下文章