使用值累积地图中的元素总和

时间:2009-04-06 14:58:36

标签: c++ algorithm stl

说我有一个

struct SMyStruct 
{
   int MULT;
   int VAL;

};


std::map<std::string, SMyStuct*> _idToMyStructMap;

现在我想计算所有SMyStuct的总和,其中total被定义为idToMyStructMap中每个元素的MULT1 * VAL1 + MULT2 * VAL2。

似乎累积功能是一个自然的选择。请建议。感谢

请不要提升......只是'时尚stl

3 个答案:

答案 0 :(得分:13)

typedef std::map< std::string, SMyStruct* > string_to_struct_t;

int add_to_totals( int total, const string_to_struct_t::value_type& data )
{
    return total + data.second->MULT * data.second->VAL; 
}

const int total = std::accumulate(
                         _idToMyStructMap.begin(),
                         _idToMyStructMap.end(),
                         0, 
                         add_to_totals );

答案 1 :(得分:6)

主题的变体是为你的struct定义operator +,然后在默认模式下使用std :: accumulate。

int & operator+ (const int &lhs, const SMyStruct &rhs){
    return lhs + (rhs.MULT * rhs.VALUE);
}

然后:

std::accumulate(_idToMyStructMap.begin(), _idToMyStructMap.end(), 0);

当然,如果operator+对于你的结构有一般意义,那么你也想在左边添加使用SMyStruct的重载,和/或使它们成为模板以便你获得int的函数所有在一个镜头中,浮动,双倍,长,等。正如jalf在评论中提到的那样,如果operator+(或它的这个版本)对你的结构一般没有意义,那么另一个解决方案就更好了。

答案 2 :(得分:1)

您还可以将“计算第二对”功能与“计算MULT * VAL”和“将某些内容添加到累加器”分开。

虽然你不需要提升来做到这一点,但他们已经创建了大量的“功能”编程框架。如果你不能使用boost,你需要一些你自己的模板魔法。但是,复杂了。

#include <map>
#include <algorithm>
#include <numeric>
#include <functional>
#include <iostream>

现在我认为将乘法放在类中更好。

struct SMyStruct 
{
   int MULT;
   int VAL;
   long f() const { return MULT*VAL; }
};

为'第二对'创建一个通用仿函数:

// a 'take-second' functor
template< typename at_pair >
struct to_second_t : public std::unary_function< at_pair, typename at_pair::second_type > {
  const typename at_pair::second_type& operator()( const at_pair & p ) const {
    return p.second;
  }
};

这看起来很棘手,但仅仅是一种通用的说法:'首先这样做,然后用结果做到:'

// compose two functors (simplified)
template< typename at_F, typename at_G >
struct compose_t : public std::unary_function< typename at_F::argument_type, typename at_G::result_type >{
    at_F f;
    at_G g;
    compose_t( at_F& f, at_G& g ): f( f ), g(g) {}

    typename at_G::result_type operator()( const typename at_F::argument_type& v ) const {
        return g( f( v ) );
    }
};

template< typename at_F, typename at_G >
compose_t<at_F, at_G> compose( at_F& f, at_G& g ) { return compose_t<at_F,at_G>( f, g ); }



// compose two functors (a unary one, and a binary one)
//
template< typename at_F, typename at_G >
struct compose2_t : public std::binary_function< typename at_F::first_argument_type, typename at_G::argument_type, typename at_G::result_type >{
    at_F f;
    at_G g;
    compose2_t( at_F& f, at_G& g ): f( f ), g(g) {}

    typename at_G::result_type operator()( const typename at_F::first_argument_type& a1, const typename at_G::argument_type& v ) const {
        return f( a1, g( v ) );
    }
};

template< typename at_F, typename at_G >
compose2_t<at_F, at_G> compose2( at_F& f, at_G& g ) { return compose2_t<at_F,at_G>( f, g ); }

最后,将其全部付诸实践:

int main()
{
  typedef std::map<int, SMyStruct > tMap; 
  tMap m;
  SMyStruct s = {1,2};
  m[1].VAL = 1; m[1].MULT = 3;
  m[2].VAL = 2; m[2].MULT = 10;
  m[3].VAL = 3; m[3].MULT = 2;

  // mind, this is not LISP (yet)
  long total = std::accumulate( m.begin(), m.end(), 0, 
    compose2( 
      std::plus<int>(),  
      compose( 
        to_second_t<tMap::value_type>(), 
        std::mem_fun_ref( &SMyStruct::f ) ) )
    );

  std::cout << "total: " << total <<std::endl;
  return 0;
}