2013-12-10 9 views
9

私はstd::istreamから取得した番号の束の合計を計算したい場合は、私は次の操作を行うことができますが:ラン同じ入力イテレータ範囲に並んで2 <algorithm>の側

// std::istream & is = ... 
int total = std::accumulate(std::istream_iterator<int>(is), 
          std::istream_iterator<int>(), 
          0); 

しかし、私の場合その平均値を計算したい、私は2つの異なる結果を蓄積する必要があります。

  • 合計(std::accumulate
  • 総数(std::distance

これら2つのアルゴリズムを「マージ」し、イテレータ範囲の1回のパスで「並列」する方法はありますか?私は次のようなことをしたい:

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; 

これは可能ですか?

答えて

11

このようなシングルパス累算の既製の解決法は、Boost.Accumulatorsによって実装されています。 1つのアキュムレータを作って、合計、数、平均などを計算し、それを入力して、最後に3つの結果をすべて抽出します。

9

インターリーブする2つの異なるアルゴリズムをマージすることはできません。アルゴリズムはフローを制御し、フローは1つしかありません。さて、あなたはそれをシミュレートすることができ、あなたの特定のケースでは:

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; }); 
-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; 
} 
関連する問題