将向量中的结构成员求和 [英] Summing struct members inside a vector
问题描述
请考虑以下内容:
typedef struct {
int a;
int b;
int c;
int d;
} ABCD;
typedef std :: vector< ABCD> VecABCD;
说我想在VecABCD类型的向量中加上每个'a'简单!
int CalcSumOfA(const VecABCD& vec)
{
int sumOfA = 0;
VecABCD :: const_iterator it;
for(it = vec.begin(); it!= vec.end(); it ++)
sumOfA + = it-> a;
return sumOfA;
}
说我想用'b'做同样的事情吗?简单!我写....基本上相同的功能,但只有微不足道的变化。与'c'和'd'相同。
那么,有没有更简洁,更不重复的做法?我想做一些像:
int sumOfA = SumOfMembers(myVec,a);
但我不能想象我如何把这样的函数放在一起。理想情况下,它将是一个模板,我可以使用它与任何种类的结构的向量,而不是特定绑定到VecABCD。任何人都有任何想法?
STL求和可以使用 std :: accumulate
#include< functional>
accumulate(v.begin(),v.end(),0,bind(plus< int>(),_1,bind(& ABCD :: a,_2)))
如果你想让这个更通用,你可以采取一个tr1 ::函数给你想要的成员bind:
int sum_over_vec(const vector< ABCD>& v,const tr1 :: function< int(const ABCD& & member)
{
return accumulate(v.begin(),v.end(),
0,
bind(plus< int> b $ b _1,
bind(member,_2)));
};
// ...
int sum_a = sum_over_vec(vec,bind(& ABCD :: a,_1));
另一种方法,函数中的逻辑,将使用boost :: transform迭代器将逻辑放入迭代器中:
tr1 :: function< int(const ABCD&)> member(bind(& ABCD :: a,_1));
accumulate(make_transform_iterator(v.begin(),member),
make_transform_iterator(v.end(),member),
0);
EDITED TO ADD:C ++ 11 lambda语法
使用C ++ 11 lambdas(尽管不幸不是更短)变得更清楚:
accumulate(v.begin(),v.end(),0,
[](int sum,const ABCD& curr){return sum + curr.a});
和
int sum_over_vec(const vector< ABCD>& v,const std :: function< int(const ABCD&)&>& member)
{
return accumulate(v.begin ),v.end(),0,
[&](int sum,const ABCD& curr){return sum + member(curr});});
};
用法:
code> //使用从成员函数ptr到std :: function的转换。
int sum_a = sum_over_vec(vec,& ABCD :: a);
//或者使用自定义λ求和的方块。
int sum_a_squared = sum_over_vec(vec,
[](const ABCD& curr){return curr.a * curr.a;});
Consider the following:
typedef struct {
int a;
int b;
int c;
int d;
} ABCD;
typedef std::vector<ABCD> VecABCD;
Say I wanted to add up every 'a' member in a vector of type VecABCD. Easy! I just loop through the vector, and sum as I go.
int CalcSumOfA(const VecABCD &vec)
{
int sumOfA = 0;
VecABCD::const_iterator it;
for(it=vec.begin();it!=vec.end();it++)
sumOfA += it->a;
return sumOfA;
}
Say I wanted to do the same thing with 'b'? Easy! I'd write....essentially the same function, but with only trivial changes. Same with 'c' and 'd'.
So, is there a more concise, less repetitive way of doing this? I'd like to do something like:
int sumOfA = SumOfMembers(myVec, a);
but I can't conceive of how I'd put such a function together. Ideally, it'd be a template, and I could use it with a vector of any kind of structure, not specifically bound to VecABCD. Anyone have any ideas?
STL summations can be done with std::accumulate
#include <functional>
accumulate(v.begin(), v.end(), 0, bind(plus<int>(), _1, bind(&ABCD::a, _2)))
If you wanted this to be more generic, you could take a tr1::function to the member you want to bind:
int sum_over_vec(const vector<ABCD>& v, const tr1::function<int (const ABCD&)>& member)
{
return accumulate(v.begin(), v.end(),
0,
bind(plus<int>(),
_1,
bind(member, _2)));
};
// ...
int sum_a = sum_over_vec(vec, bind(&ABCD::a, _1));
Another way to do it, rather than putting your logic in the functor, would be to put the logic in the iterator, using a boost::transform iterator:
tr1::function<int (const ABCD&)> member(bind(&ABCD::a, _1));
accumulate(make_transform_iterator(v.begin(), member),
make_transform_iterator(v.end(), member),
0);
EDITED TO ADD: C++11 lambda syntax
This becomes somewhat clearer with the C++11 lambdas (though unfortunately not shorter):
accumulate(v.begin(), v.end(), 0,
[](int sum, const ABCD& curr) { return sum + curr.a });
and
int sum_over_vec(const vector<ABCD>& v, const std::function<int (const ABCD&)>& member)
{
return accumulate(v.begin(), v.end(), 0,
[&](int sum, const ABCD& curr) { return sum + member(curr}); });
};
Usage:
// Use a conversion from member function ptr to std::function.
int sum_a = sum_over_vec(vec, &ABCD::a);
// Or using a custom lambda sum the squares.
int sum_a_squared = sum_over_vec(vec,
[](const ABCD& curr) { return curr.a * curr.a; });
这篇关于将向量中的结构成员求和的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!