累积中的 Lambda 函数

Lambda function in accumulate

我正在尝试学习如何使用 lamba 函数,并想做一些类似的事情:

给定一个向量 = {1,2,3,4,5}

我想要两两之和 = (1+2)+(2+3)+...

以下是我的尝试,但效果不佳。

#include <vector>
#include <algorithm>

using namespace std;

vector <double> data = {1,10,100};

double mean = accumulate(data.begin(),data.end(),0.0);

double foo()
{
    auto bar = accumulate(data.begin(),data.end(),0.0,[&](int k, int l){return (k+l);});

    return bar
}

我尝试将 return 语句更改为 return (data.at(k)+data.at(l)),但效果不佳。

您误解了 std::accumulate 的工作原理。假设你有 int array[],然后累积:

int value = initial_val;
value = lambda( value, array[0] );
value = lambda( value, array[1] );
...
return value;

这是伪代码,但应该很容易理解它是如何工作的。所以在你的情况下 std::accumulate 似乎不适用。您可以编写一个循环,或创建您自己的特殊 accumulate 函数:

auto lambda = []( int a, int b ) { return a + b; };
auto sum = 0.0;
for( auto it = data.begin(); it != data.end(); ++it ) {
    auto itn = std::next( it );
    if( itn == data.end() ) break;
    sum += lambda( *it, *itn );
}

您可以在 lambda 中捕获一个变量以保留最后一个值:

#include <vector>
#include <algorithm>
#include <numeric>

std::vector<double> data = {1,10,100};

double mean = accumulate(data.begin(), data.end(), 0.0);

double foo()
{
    double last{0};
    auto bar = accumulate(data.begin(), data.end(), 0.0, [&](auto k, auto l) 
    {
        auto total = l + last; 
        last = l; 
        return total+k; 
    });

    return bar;
}

int main()
{
    auto val = foo();
}

您可以使用某种索引,然后添加下一个数字。

size_t index = 1;
auto bar = accumulate(data.begin(), data.end(), 0.0, [&index, &data](double a, double b) {
    if (index < data.size())
        return a + b + data[index++];
    else 
        return a + b;
});

请注意,您有一个 double 的向量,但正在使用 int 求和。

成对求和与对除第一个和最后一个元素之外的所有内容求和两次相同。不需要花哨的 lambda。

auto result = std::accumulate(std::begin(data), std::end(data), 0.0)
  * 2.0 - data.front() - data.end();

或者更安全一点:

auto result = std::accumulate(std::begin(data), std::end(data), 0.0) 
   * 2.0 - (!data.empty() ? data.front() : 0) - (data.size() > 1 ? data.back() : 0);

如果你坚持使用lambda,你可以把加倍移到里面:

result = std::accumulate(std::begin(data), std::end(data), 0.0, 
   [](double lhs, double rhs){return lhs + 2.0*rhs;}) 
   - data.front() - data.back();

请注意,lambda 中的 lhs 当前总和 ,而不是序列中接下来的两个数字。

如果您坚持在 lambda 中完成所有工作,您可以使用 generalized capture:

跟踪索引
result = std::accumulate(std::begin(data), std::end(data), 0.0, 
       [currIndex = 0U, lastIndex = data.size()-1] (double lhs, double rhs) mutable
       {
          double result = lhs + rhs;
          if (currIndex != 0 && currIndex != lastIndex)
             result += rhs;
          ++currIndex;
          return result;
       });

Demo of all approaches