使用 std::accumulate

发布于 2024-07-14 05:25:41 字数 1019 浏览 2 评论 0原文

需要以下示例的更漂亮的解决方案,但使用 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;
}

Need prettier solution of below example but with 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;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

隔纱相望 2024-07-21 05:25:41

更改计算器和主要功能。

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

do changes in Calculator and main 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;
}

also it could be better:

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

double result = std::accumulate( collection.begin(), collection.end(), 0, sumABProduct );
烟雨凡馨 2024-07-21 05:25:41

更新 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 手册。

Update 2: Boost.Lambda makes this a piece of cake:

// 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;

Update: This has been bugging me for a while. I can't just get any of the STL algorithms to work in a decent manner. So, I rolled my own:

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

Of course, the original solution still holds:
The easiest is to implement an operator+. In this case:

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

and make it a friend of Object or member (look up why you may prefer one over the other):

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

and you're done with:

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

My earlier approach doesn't work because we need a binary_function.

std::accumulate manual.

治碍 2024-07-21 05:25:41

这里有一个问题,我猜参数的编写顺序应该是错误的:

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

在这种累加的情况下,结果包含在返回的对象中。

如果您使用 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(), 0.0,Adapt())

由于一些奇怪和愚蠢的原因,不能在 gnu 并行模式下工作。

here is an issue here, I guess the arguments are written in the wrong order should be:

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

in this case of accumulate, the result is contained in a returned Object.

If you are using gnu parallel mode the functor will give you problems if the result and the actual object referred to by the iterator are different.

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())

will not work with gnu parallel mode for some strange and silly reason.

贱贱哒 2024-07-21 05:25:41

使用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;
} 

Using 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;
} 
风苍溪 2024-07-21 05:25:41

人们希望这是一份家庭作业……

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 的声明。

One would hope this is homework...

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

and

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

assuming you're not allowed to touch the declaration of Object.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文