无输出变换

时间:2015-07-30 19:02:16

标签: c++ loops vector transform stl-algorithm

我有两个相同大小的vector个。我需要通过另一个vector的内容修改一个vector的每个元素。是否有标准算法可以完成此操作而无需返回原始vector

所以说我想通过vector foo的相应元素修改vector bar的所有元素。我可以使用transform

transform(foo.begin(), foo.end(), bar.begin(), foo.begin(), [](auto& a, const auto& b){a.func(b); return a;});

但是回到foo的分配是不必要的。或者,我可以编写自己的函数:

auto a = foo.begin();
auto b = bar.begin();

while(a != foo.end()){
    (a++)->func(*(b++));
}

但是如果已经存在某些东西,我宁愿不重新发明轮子。

3 个答案:

答案 0 :(得分:2)

对于二进制函数,您要求的基本上是std::for_each。 由于还没有这样的东西,你可以做以下其中一件事:

1)为二进制函数实现此类for_each的通用版本:

(代码取自https://groups.google.com/a/isocpp.org/d/msg/std-proposals/fNqx2TR-ju8/MIqPwgSoWukJ

#include <vector>
#include <iostream>

template<class InputIt1, class InputIt2, class BinaryFunction>
BinaryFunction for_each(InputIt1 first1, InputIt1 last1, InputIt2 first2, BinaryFunction f)
{
    for (; first1 != last1; ++first1, ++first2) {
        f(*first1, *first2);
    }
    return f;
}

struct Foo
{
    Foo() : k(-1){}
    int k;
    void func(int i){k=i;}
};

int main() {

    std::vector<Foo> foo(5);
    std::vector<int> bar(5,55);

    for_each(foo.begin(), foo.end(), bar.begin(), [](auto& a, const auto& b){a.func(b); return a;});

    for(auto f : foo)
    {
        std::cout << f.k << std::endl;
    }
    return 0;
}

<强> live on coliru

2)使用boost::zip_iterator和现有std::for_each

#include <algorithm>
#include <vector>
#include <iostream>

#include <boost/iterator/zip_iterator.hpp>

struct Foo
{
    Foo() : k(-1){}
    int k;
    void func(int i){k=i;}
};

template<typename... Iterators>
auto zip(Iterators... its)
{
    return boost::make_zip_iterator(boost::make_tuple(its...));
}

int main() {

    std::vector<Foo> foo(5);
    std::vector<int> bar(5,55);

    auto zip_func = [](auto&& t){t.template get<0>().func(t.template get<1>());};
    std::for_each(
        zip(foo.begin(), bar.begin()),
        zip(foo.end(), bar.end()),
        zip_func
    );

    for(auto f : foo)
    {
        std::cout << f.k << std::endl;
    }
    return 0;
}

<强> live on coliru

答案 1 :(得分:0)

对此最干净的答案似乎是使用索引而不是迭代器。

for(auto i = 0; i < foo.size(); ++i) foo[i].func(bar[i]);

它的唯一要求类似于任何多输入迭代器算法的要求:所有容器必须至少具有第一对迭代器指示的相同范围。这意味着所有容器的大小应大于或等于foo.size()。与滥用transform不同,这可以扩展为支持尽可能多的包含操作员的容器:

for(auto i = 0; i < foo.size(); ++i) foo[i].func(bar[i], baz[i], buz[i]);

答案 2 :(得分:0)

小实用功能模板:

template <typename Input1, typename Input2, typename BinaryOperation>
void zip(Input1 b1, Input1 e1, Input2 b2, BinaryOperation binOp) {
    while (b1 != e1) binOp(*b1++, *b2++);
}

用法:

zip(begin(foo), end(foo), begin(bar), [](auto& a, const auto& b){ a.func(b); });