繁体   English   中英

使用 std::accumulate

[英]using of std::accumulate

需要以下示例的更漂亮的解决方案,但使用 std::accumulate。

#include <algorithm>
#include <vector>
#include <iostream>

class Object
{
public:
    Object( double a, double b ):
        a_( a ),
        b_( b )
    {}

    double GetA() const { return a_; }
    double GetB() const { return b_; }
    // other methods
private:
    double a_;
    double b_;
};

class Calculator
{
public:
    Calculator( double& result ):
        result_( result )
    {}

    void operator() ( const Object& object )
    {
        // some formula
        result_ += object.GetA() * object.GetB();
    }
private:
    double& result_;
};

int main()
{
    std::vector< Object > collection;
    collection.push_back( Object( 1, 2 ) );
    collection.push_back( Object( 3, 4 ) );

    double result = 0.0;
    std::for_each( collection.begin(), collection.end(),
                   Calculator( result ) );

    std::cout << "result = " << result << std::endl;

    return 0;
}

在计算器和主 function 中进行更改。

struct Calculator
{
    double operator() ( double result, const Object& obj )
    {
        return result + ( obj.GetA() * obj.GetB());
    }

};

int main()
{
    std::vector< Object > collection;
    collection.push_back( Object( 1, 2 ) );
    collection.push_back( Object( 3, 4 ) );

    double result = std::accumulate( collection.begin(), collection.end(), 0, Calculator() );
    std::cout << "result = " << result << std::endl;

    return 0;
}

也可以更好:

double sumABProduct( double result, const Object& obj )
{
    return result + ( obj.GetA() * obj.GetB());
}

double result = std::accumulate( collection.begin(), collection.end(), 0, sumABProduct );

更新 2: Boost.Lambda 使这小菜一碟:

// headers
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>
using namespace boost::lambda;
// ...
cout << accumulate(dv.begin(), dv.end(), 
                   0, 
                   _1 += bind(&strange::value, _2)) //strange defined below
     << endl;

更新:这一直困扰着我一段时间。 我不能让任何 STL 算法以体面的方式工作。 所以,我推出了自己的:

// include whatever ...
using namespace std;

// custom accumulator that computes a result of the 
// form: result += object.method();
// all other members same as that of std::accumulate
template <class I, class V, class Fn1, class Fn2>
V accumulate2(I first, I last, V val, Fn1 op, Fn2 memfn) {
    for (; first != last; ++first)
        val = op(val, memfn(*first));
    return val;
}

struct strange {
    strange(int a, int b) : _a(a), _b(b) {}
    int value() { return _a + 10 * _b; }
    int _a, _b;
};

int main() {
    std::vector<strange> dv;
    dv.push_back(strange(1, 3));
    dv.push_back(strange(4, 6));
    dv.push_back(strange(20, -11));        
    cout << accumulate2(dv.begin(), dv.end(), 
                        0, std::plus<int>(), 
                        mem_fun_ref(&strange::value)) << endl;
}

当然,最初的解决方案仍然成立:最简单的是实现operator+ 在这种情况下:

double operator+(double v, Object const& x) {
        return v + x.a_;
}

并使其成为Object或会员的朋友(查看为什么您可能更喜欢其中一个):

class Object
{
   //...
  friend double operator+(double v, Object const& x);

你完成了:

 result = accumulate(collection.begin(), collection.end(), 0.0);

我之前的方法不起作用,因为我们需要一个binary_function

std::accumulate手册。

使用 c++0x:

#include <numeric>
#include <vector>
#include <iostream>

class Object
{
  public:
     Object( double a, double b ):
        a_( a ),
        b_( b )
      {}

    double GetA() const { return a_; }
    double GetB() const { return b_; }
    // other methods
  private:
    double a_;
    double b_;
};

int main()
{
    std::vector< Object > collection;
    collection.push_back( Object( 1, 2 ) );
    collection.push_back( Object( 3, 4 ) );
    double result = std::accumulate( collection.begin(), collection.end(), 0,
                                     [] (double result, const Object& obj) 
                                     {
                                       return result + obj.GetA() * obj.GetB();
                                     }
                                   ); 

   std::cout << "result = " << result << std::endl;

   return 0;
} 

这里有个问题,我猜arguments的写错顺序应该是:

result = std::accumulate(collection.begin(), collection.end(), Object(0),Adapt())
where Adapt is defined thus:

struct Adapt { 
    static double mul(Object const &x) { return x.GetA() * x.GetB(); }
    static Object operator()(Object const &x, Object const &y) { 
       return Object(mul(x)+mul(y)) ; } };

在这种累积的情况下,结果包含在返回的 Object 中。

如果您使用 gnu 并行模式,如果结果与迭代器引用的实际 object 不同,则仿函数会给您带来问题。

struct Adapt { 
        static double mul(Object const &x) { return x.GetA() * x.GetB(); }
        static double operator()(Object const &x, Object const &y) { 
           return mul(x)+mul(y) ; } };
result = std::accumulate(collection.begin(), collection.end(), 0.0,Adapt())

由于某些奇怪和愚蠢的原因,无法使用 gnu 并行模式。

希望这是家庭作业...

struct Adapt { 
    static double mul(Object const &x) { return x.GetA() * x.GetB(); }
    static double operator()(Object const &x, Object const &y) { 
       return mul(x)+mul(y); } };

result = std::accumulate(collection.begin(), collection.end(), Object(0,0),Adapt() );

假设您不允许触摸 Object 的声明。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM