Лямбда-функция в накоплении

Я пытаюсь узнать, как использовать функции 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)), что не вполне сработало.

1

Решение

Добавление попарных сумм аналогично суммированию по всему дважды, кроме первого и последнего элементов. Нет необходимости в причудливой лямбде.

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

Если вы настаиваете на лямбде, вы можете переместить удвоение внутрь:

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

Обратите внимание, что lhs внутри лямбда это текущая сумма, не следующие два числа в последовательности.

Если вы настаиваете на выполнении всей работы в лямбде, вы можете отслеживать индекс, используя обобщенный захват:

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

Демо всех подходов

3

Другие решения

Вы неправильно поняли, как 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

Вы можете перехватить переменную в лямбде, чтобы сохранить последнее значение:

#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();
}
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с суммой.

1
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector