Assumed I would like to add two vectors a
and b
into a vector c
std::vector<double> a, b, c;
//Fill/Initialize vectors
I can either use std::transform()
or a simple for
-loop:
//std::transform
std::transform(a.begin(),
a.end(),
b.begin(),
c.begin(),
[](const auto &a_val, const auto &b_val){
return a_val + b_val;
});
//Loop
for(size_t i = 0; i < a.size(); ++i){
c[i] = a[i] + b[i];
}
Usually, using std::transform()
is recommended compaired to a for
-loop. Unfortunately, as far as I know, I can not do a similar approach using std::transform()
for the case of adding up more vectors than two, i.e. if I would like to add up the vectors a
, b
and c
into d. Then I'm back to the for-loop, or I have to use two rounds of std::transform()
. Or is there a way of using a single std::transform()
-operation (or something similar) for operating on more than two input vectors at the same time?
It's true, in standard library this is impossible to std::transform
more than 2 vectors. But using range-v3
you can do it with arbitrary number of vectors using zip
.
#include <include/range/v3/view/zip.hpp>
int main()
{
std::vector<int> a{1,2,3};
std::vector<int> b{2,3,4};
std::vector<int> c{2,3,4};
std::vector<int> d{2,3,4};
std::vector<int> res;
auto r = ranges::views::zip(a, b, c, d);
std::transform(
r.begin(),
r.end(),
std::back_inserter(res),
[](const auto& tup) { return std::get<0>(tup); }
);
}
If you are fine with creating another vector you can do this:
#include <iostream>
#include <vector>
#include <numeric>
#include <algorithm>
int main() {
std::vector<int> a{1,2,3,4};
std::vector<int> b{1,2,3,4};
std::vector<int> c(a.size());
std::vector<int> v(a.size());
std::iota(v.begin(), v.end(),0);
std::transform(v.begin(),
v.end(),
c.begin(),
[&](const auto &i){
return a[i] + b[i];
});
for (const auto& e : c) std::cout << e << ' ';
return 0;
}
You could turn the lambda into something more generic, eg a functor that works on variadic number of vectors and adds their elements.
However, I would prefer the loop. Main advantage of algorithms is clarity, but if you need to resort to a workaround that clarity is lost. Maybe someone can proove me wrong and find an algorithm that can do what you want out of the box ;).
PS: on a second thought the above is really silly and a misuse of the algorithm. With the help of std::iota
any loop can trivially be transformed to using an algorithm, but the true meaning of std::transform
"transform one range to another" is completely lost which defeats the purpose of using an algorithm in the first place.
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