Given a block size N
and a vector of integers of length k * N
which can be viewed as k
blocks of N
integers, I want to create a new vector of length k
whose elements are the sums of the blocks of the original vector.
E.g. block size 2, vector {1,2,3,4,5,6}
would give a result of {3,7,11}
.
E.g. block size 3, vector {0,0,0,1,1,1}
would give a result of {0,3}
.
A simple approach that works:
std::vector<int> sum_blocks(int block_size, const std::vector<int>& input){
std::vector<int> ret(input.size() / block_size, 0);
for (unsigned int i = 0; i < ret.size(); ++i)
{
for(unsigned int j=0; j < block_size; ++j)
ret[i] += input[block_size * i + j];
}
return ret;
}
However I'd be interested in knowing if there is a neater or more efficient way of doing this, possibly using the algorithm
library.
If you can use the range-v3 library, you could write the function like this:
namespace rv = ranges::views;
namespace rs = ranges;
auto sum_blocks(int block_size, std::vector<int> const & input)
{
return input
| rv::chunk(block_size)
| rv::transform([](auto const & block) {
return rs::accumulate(block, 0);
})
| rs::to<std::vector<int>>;
}
which is quite self-explanatory, and avoids doing any arithmetic like block_size * i + j
, which is error prone.
demo.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With