Я пытаюсь узнать, как использовать функции 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)), что не вполне сработало.
Добавление попарных сумм аналогично суммированию по всему дважды, кроме первого и последнего элементов. Нет необходимости в причудливой лямбде.
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;
});
Вы неправильно поняли, как 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 );
}
Вы можете перехватить переменную в лямбде, чтобы сохранить последнее значение:
#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
с суммой.