9

から取得した一連の数値の合計を計算する場合std::istreamは、次のようにします。

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

ただし、それらの平均を計算するには、2 つの異なる結果を累積する必要があります。

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

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

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;

これは可能ですか?

4

3 に答える 3

11

この種のシングルパス累積の既製のソリューションは、Boost.Accumulatorsによって実装されます。たとえば、合計、カウント、平均などの単一のアキュムレータを作成し、データを入力してから、最後に 3 つの結果すべてを抽出します。

于 2013-12-10T18:54:21.377 に答える
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; });
于 2013-12-10T18:56:19.200 に答える
-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;
}
于 2013-12-10T19:20:20.387 に答える