std::transform 对于两个以上的向量
std::transform for more than two vectors
假设我想将两个向量 a
和 b
添加到向量 c
中
std::vector<double> a, b, c;
//Fill/Initialize vectors
我可以使用 std::transform()
或简单的 for
循环:
//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];
}
通常,建议使用 std::transform()
与 for
循环进行比较。不幸的是,据我所知,对于相加多于两个的向量的情况,我无法使用 std::transform()
执行类似的方法,即如果我想将向量相加 a
,b
和 c
到 d。然后又回到for循环,要不我就得用两轮std::transform()
。或者有没有一种方法可以使用单个 std::transform()
-operation(或类似的东西)同时对两个以上的输入向量进行操作?
的确,在标准库中,std::transform
不可能有超过 2 个向量。但是使用 range-v3
你可以使用 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); }
);
}
如果您可以创建另一个矢量,您可以这样做:
#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;
}
您可以将 lambda 变成更通用的东西,例如,一个作用于可变数量的向量并添加它们的元素的函子。
不过,我更喜欢循环。算法的主要优点是清晰,但如果您需要求助于一种变通方法,那么清晰度就会丢失。也许有人可以证明我是错的,并找到一个可以开箱即用的算法 ;)。
PS:转念一想,上面的内容确实很愚蠢,是对算法的误用。在 std::iota
的帮助下,任何循环都可以简单地转换为使用算法,但是 std::transform
"transform one range to another" 的真正含义完全丢失,这首先违背了使用算法的目的.
假设我想将两个向量 a
和 b
添加到向量 c
std::vector<double> a, b, c;
//Fill/Initialize vectors
我可以使用 std::transform()
或简单的 for
循环:
//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];
}
通常,建议使用 std::transform()
与 for
循环进行比较。不幸的是,据我所知,对于相加多于两个的向量的情况,我无法使用 std::transform()
执行类似的方法,即如果我想将向量相加 a
,b
和 c
到 d。然后又回到for循环,要不我就得用两轮std::transform()
。或者有没有一种方法可以使用单个 std::transform()
-operation(或类似的东西)同时对两个以上的输入向量进行操作?
的确,在标准库中,std::transform
不可能有超过 2 个向量。但是使用 range-v3
你可以使用 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); }
);
}
如果您可以创建另一个矢量,您可以这样做:
#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;
}
您可以将 lambda 变成更通用的东西,例如,一个作用于可变数量的向量并添加它们的元素的函子。
不过,我更喜欢循环。算法的主要优点是清晰,但如果您需要求助于一种变通方法,那么清晰度就会丢失。也许有人可以证明我是错的,并找到一个可以开箱即用的算法 ;)。
PS:转念一想,上面的内容确实很愚蠢,是对算法的误用。在 std::iota
的帮助下,任何循环都可以简单地转换为使用算法,但是 std::transform
"transform one range to another" 的真正含义完全丢失,这首先违背了使用算法的目的.