我正在阅读以下问题:
How to sum up elements of a C++ vector?,我想使用第二种方法(sum_of_elems =std::accumulate(vector.begin(),vector.end(),0);//#include <numeric>
)。
但是,我没有std::vector<int>
,而是std::vector<struct packet>
。 packet
定义如下:
struct packet {
/// ...
int length() const;
///
}
我需要数据包长度的总和。
这就是我的尝试:
std::vector<packet> packets;
...
std::accumulate(packets.begin(), packets.end(), 0, [](const packet& a, const packet& b){return a.length() + b.length();});
但它不起作用。在C#中,我会写一些类似
的内容packet[] p;
p.Select(x => p.length()).Sum();
是否有可能在C ++中做类似的事情?我可以编写迭代矢量并自己完成的方法,但我更喜欢功能方法。
答案 0 :(得分:4)
我会注意到C#实现本质上略有不同。
在C ++中,您尝试添加int
和packet
,而在C#中,您首先提供从packet
到int
的转换步骤,然后添加int
第
等效的C ++,没有改编:
std::vector<size_t> lengths; // a length cannot be negative!
std::transform(packets.begin(),
packets.end(),
backward_inserter(lengths),
[](packet const& p) { return p.length(); });
auto const sum = std::accumulate(lengths.begin(), lengths.end(), 0ul);
当然,存放中间长度是浪费的,但它可以开箱即用。
但是因为我们很酷,让我们看看Boost.Range
,更准确地说:
像林奇一样有点冷静:
#include <boost/range/numeric.hpp> // accumulate
#include <boost/range/adaptor/transformed.hpp>
size_t total_size(std::vector<packet> const& packets) {
return boost::accumulate(
packets | boost::transformed([](packet const& p) { return p.length(); }),
0ul);
}
答案 1 :(得分:3)
您正在通过二进制操作进行累积。您的累计值以0
(int
)开头,因此二进制操作的左侧必须可以从0
转换 - 否则,它是如何开始添加的? / p>
试试这个:
std::accumulate(
packets.begin(),
packets.end(),
0,
[](int a, const packet& b){
return a + b.length();
}
);
你也可以通过一个简单的循环来完成这个:
int acc = 0;
for( const packet& p : packets ) {
acc += packets.length();
}
答案 2 :(得分:2)
累积操作的第一个参数是运行总计。在你的情况下,这是一个整数,而不是一个数据包,所以你的lambda应该是
[](int a, const packet& b) {return a + b.length();}
答案 3 :(得分:1)
问题在于你的累积功能。它的第一个参数必须是您尝试累积的类型(在这种情况下为int
)并在其上添加一个值。
您的lambda函数应如下所示:[](int currTotal, const packet& b){return currTotal + b.length();}
答案 4 :(得分:1)
除了lamba,您可以将其更改为
std::accumulate(packets.begin(), packets.end(), 0, packet());
您可以将仿函数定义为:
int operator() (int result, const packet& obj)
{
return result+ obj.length();
}