代码之家  ›  专栏  ›  技术社区  ›  Mykola Golubyev

std::累加的使用

  •  7
  • Mykola Golubyev  · 技术社区  · 17 年前

    需要以下示例的更漂亮的解决方案,但使用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;
    }
    
    5 回复  |  直到 15 年前
        1
  •  12
  •   bayda    17 年前

    对计算器和主功能进行更改。

    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
  •  3
  •   dirkgently    17 年前

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

        3
  •  1
  •   Painless Coding    15 年前

    这里有一个问题,我想论点的顺序是错误的,应该是:

    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并行模式一起工作。

        4
  •  1
  •   Andy Sardina Ramos    11 年前

    使用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;
    } 
    
        5
  •  0
  •   Painless Coding    15 年前

    希望这是家庭作业。。。

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

    假设你不允许触摸对象的声明。