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

sum of non-integer elements in std::vector

本文关键字:元素 整数 vector std      更新时间:2023-10-16

我正在阅读以下问题:如何对C++向量的元素求和?,我想使用第二种方法(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++中可以做这样的事情吗?我可以编写迭代向量的方法,并自己完成,但在可能的情况下,我更喜欢函数方法。

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

在C++中,您尝试添加intpacket,而在C#中,您首先提供从packetint的转换步骤,然后添加int s。

等效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,更准确地说:

  • boost::accumulate
  • boost::transformed

像Linq:一样有点酷

#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);
}

您通过二进制运算进行累加。您的累积值以0(一个int)开始,所以二进制运算的左手边必须可以从0转换——否则,它是如何开始加法的?

试试这个:

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

累加运算的第一个参数是运行总数。在您的情况下,这是一个整数,而不是一个数据包,所以您的lambda应该是

[](int a, const packet& b) {return a + b.length();}

问题出在累积函数上。它的第一个参数必须是您试图累积的类型(在本例中为int),并在此基础上添加一个值。

您的lambda函数应该如下所示:[](int currTotal, const packet& b){return currTotal + b.length();}

除了lamba,您还可以将其更改为

std::accumulate(packets.begin(), packets.end(), 0, packet());

您可以将函子定义为:

int operator() (int result, const packet& obj)
{
    return result+ obj.length();
}