【问题标题】:Run two <algorithm>s side by side on the same input iterator range在同一输入迭代器范围内并排运行两个 <algorithm>
【发布时间】: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;

这可能吗?

【问题讨论】:

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


    【解决方案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;
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-01-28
          • 2021-12-04
          • 2012-11-05
          • 2011-10-28
          • 1970-01-01
          • 1970-01-01
          • 2014-10-14
          • 1970-01-01
          相关资源
          最近更新 更多