Can you access the current iterator from a function used by the transform function in c so that you can reference previous and latter values? I want to use the transform function to iterate through a vector, performing operations on the vector that rely on values before and after the current value.
For example, say I have a vector with values [1,2,4,3,5,6], and I want to start at the second value, and iterate until the second to last value. On each of those elements, I want to make a new value that equals the sum of the value, and the values next to it in the original. The ending vector would look like [7,9,12,14].
auto originalsBeginIterator = originalPoints.begin();
auto originalsEndIterator = originalPoints.end();
std::advance(originalsBeginIterator, 1);
std::advance(originalsEndIterator,-1);
std::transform(originalsBeginIterator,originalsEndIterator,alteredValues.begin(),
[](int x) x = { return {previous value} x {next value};}
);
Is there any way to reference previous and latter values from the original array when using transform?
CodePudding user response:
Clearly the tool std::transform
simply doesn't give you a way to do that: it either takes a unary predicate to be applied to individual elements of of one collection, or a binary predicate to be applied to corresponding elements of two collections.
But the point is that, from the functional programming perspective, what you are trying to do is simply not a transform.
How can you go about it instead? You could zip that vector, let's call it v
, the same vector deprived of its first element, and the same vector deprived from its second element; you would then sum the 3 elements of each pair.
Range-v3 gives you a way to do this quite tersely:
#include <iostream>
#include <range/v3/view/drop.hpp>
#include <range/v3/view/transform.hpp>
#include <range/v3/view/zip_with.hpp>
#include <vector>
using namespace ranges::views;
int main()
{
// input
std::vector<int> v{1,2,3,4,5,6};
// to sum 3 ints
auto constexpr plus = [](int x, int y, int z){ return x y z; };
// one-liner
auto w = zip_with(plus, v, v | drop(1), v | drop(2));
// output
std::cout << w << std::endl;
}
v | drop(1)
gives you a view on the elements {2,3,4,5,6}
, and v | drop(2)
on {3,4,5,6}
; zip_with
taks a n-ary function and n ranges and combines the n-tuple of corresponding elements from the n ranges using the n-ary function. So in our case it'll go like this:
v = {1, 2, 3, 4, 5, 6}
v1 = v | drop(1) = {2, 3, 4, 5, 6}
v2 = v | drop(2) = {3, 4, 5, 6}
zip_with(plus, v, v1, v2) = {6, 9,12,15}