无输出转换
transform with No Output
我有两个相同大小的 vector
。我需要用另一个 vector
的内容修改一个 vector
的每个元素。是否有一种标准算法可以在不分配回原始 vector
的情况下完成此操作?
所以说我想用vector bar
的相应元素修改vector foo
的所有元素。我可以使用 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++));
}
但如果已经有了一些东西,我宁愿不重新发明轮子。
您要的基本上是一个 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;
}
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;
}
最简洁的答案似乎是使用索引而不是迭代器。
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]);
小型实用函数模板:
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); });
我有两个相同大小的 vector
。我需要用另一个 vector
的内容修改一个 vector
的每个元素。是否有一种标准算法可以在不分配回原始 vector
的情况下完成此操作?
所以说我想用vector bar
的相应元素修改vector foo
的所有元素。我可以使用 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++));
}
但如果已经有了一些东西,我宁愿不重新发明轮子。
您要的基本上是一个 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;
}
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;
}
最简洁的答案似乎是使用索引而不是迭代器。
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]);
小型实用函数模板:
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); });