Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accumulate absolute values of a vector

If I like to accumulate the absolute values of a std::vector, I can use a lambda to calculate the absolute value and add it to the sum of std::accumulate (live demo).

#include <numeric>
#include <vector>

int main (){
    std::vector<int> vec {1,2,3,-4};
    auto abs_val =[](auto val, auto sum){return sum + std::fabs(val);};
    return std::accumulate(vec.begin(), vec.end(), 0, abs_val);
}

I would like to write

    return std::accumulate(vec.begin(), vec.end(), 0, std::fabs());

but this does not compile, since a function with the two arguments sum and value is expected.

Is there a more elegant way to write this? Do I need the lambda? Can I get rid of it?

like image 766
schorsch312 Avatar asked Oct 07 '19 09:10

schorsch312


1 Answers

Before C++17

You basically want to do two things: Transform the elements and then sum them. For std::accumulate you have to tell the algorithm how you want to sum the elements up, but if you want to transform the elements, you need to do something extra.

The line you want to write only tells how to transform the elements (and it doesnt compile, because accumulate expects a functor that adds elements not one that transforms them).

TL;DR: No. If you want to transform and add elements, you have to do both. There is no algorithm called transform_and_accumulate, so you have to combine something yourself.

C++17

The above is true only till C++17, which has transform_reduce and that basically does what you are looking for.

like image 192
463035818_is_not_a_number Avatar answered Sep 23 '22 05:09

463035818_is_not_a_number