std :: vector中非整数元素的总和

时间:2013-08-15 13:04:18

标签: c++ vector stl functional-programming

我正在阅读以下问题: 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 ++中做类似的事情?我可以编写迭代矢量并自己完成的方法,但我更喜欢功能方法。

5 个答案:

答案 0 :(得分:4)

我会注意到C#实现本质上略有不同。

在C ++中,您尝试添加intpacket,而在C#中,您首先提供从packetint的转换步骤,然后添加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)

您正在通过二进制操作进行累积。您的累计值以0int)开头,因此二进制操作的左侧必须可以从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();
}