简体   繁体   English

两个以上向量的 std::transform

[英]std::transform for more than two vectors

Assumed I would like to add two vectors a and b into a vector c假设我想将两个向量ab添加到向量c

std::vector<double> a, b, c;
//Fill/Initialize vectors

I can either use std::transform() or a simple for -loop:我可以使用std::transform()或简单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.通常,与for循环相比,建议使用std::transform() 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, ie if I would like to add up the vectors a , b and c into d.不幸的是,据我所知,我不能使用std::transform()来做类似的方法来添加两个以上的向量,即如果我想将向量abc加到 d 中. Then I'm back to the for-loop, or I have to use two rounds of std::transform() .然后我回到 for 循环,或者我必须使用两轮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?或者有没有办法使用单个std::transform()操作(或类似的东西)同时对两个以上的输入向量进行操作?

It's true, in standard library this is impossible to std::transform more than 2 vectors.确实,在标准库中, std::transform不可能超过 2 个向量。 But using range-v3 you can do it with arbitrary number of vectors using zip .但是使用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); }
    );
}

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.您可以将 lambda 变成更通用的东西,例如,一个适用于可变数量向量并添加它们的元素的函子。

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. PS:再想一想,上面的内容真的很愚蠢,而且是对算法的误用。 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.std::iota的帮助下,任何循环都可以轻松地转换为使用算法,但是std::transform “将一个范围转换为另一个范围”的真正含义完全丧失了,这首先破坏了使用算法的目的.

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM