在相同的输入迭代器范围</algorithm>上并排运行两个<algorithm>

时间:2013-12-10 18:51:58

标签: c++ algorithm iterator stl-algorithm istream-iterator

如果我想计算从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;

这可能吗?

3 个答案:

答案 0 :(得分:11)

Boost.Accumulators实现了这种单通道累积的现成解决方案。你创建一个累加器,比如求和,计数和平均值,填充它,然后在最后提取所有三个结果。

答案 1 :(得分:9)

您无法合并两种不同的算法进行交错。算法控制流量,您只能有一个流量。现在,在您的特定情况下,您可以模拟它:

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

答案 2 :(得分:-1)

这是完全黑客攻击,但是这样的事情:

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