Lambda函数在累积

时间:2016-11-07 17:40:00

标签: c++ lambda accumulate

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

给定vector = {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)),这不太有效。

4 个答案:

答案 0 :(得分:3)

添加成对总和与除了第一个和最后一个元素之外的所有内容的求和相同。不需要花哨的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

答案 1 :(得分:2)

你误解了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 );
}

答案 2 :(得分:1)

您可以捕获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();
}

答案 3 :(得分:1)

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

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来求和。