用新向量中的对应值替换向量中的所有奇数
replace all odd values in vector with coresponing value from new vector
给定以下向量:
std::vector<int> foo{1,2,3,4,5,6,7};
std::vector<int> bar{10,20,30,40,50,60,70};
最后我希望 foo
包含值 { 10, 2, 30, 4, 50, 6, 70 }
意味着替换所有奇数。
我试过算法std::replace_if,但是如何获取柱对应的值?
// replace_copy_if example
#include <iostream> // std::cout
#include <algorithm> // std::replace_copy_if
#include <vector> // std::vector
bool IsOdd (int i) { return ((i%2)==1); }
int main () {
std::vector<int> foo{1,2,3,4,5,6,7};
std::vector<int> bar{10,20,30,40,50,60,70};
std::replace_if (foo.begin(), foo.end(), IsOdd, 0);
std::cout << "foo contains:";
for (auto i: foo){ std::cout << ' ' << i; }
std::cout << '\n';
return 0;
}
// output : foo contains: 0 2 0 4 0 6 0
// desired output : foo contains: 10 2 30 4 50 6 70
// replace_copy_if example
#include <iostream> // std::cout
#include <vector> // std::vector
int main () {
std::vector<int> foo{1,2,3,4,5,6,7};
std::vector<int> bar{10,20,30,40,50,60,70};
for (size_t i = 0; i < bar.size(); i++)
{
if (foo[i]%2==1) foo[i]=bar[i];
}
std::cout << "bar contains:";
for (auto i: foo){ std::cout << ' ' << i; }
std::cout << '\n';
return 0;
}
std::replace_if
仅支持用指定为最后一个参数的常量值替换元素。但是,如果您觉得它对您有意义,您可以基于 reference implementation 编写自己的 replace_if
函数,并使其接受某种生成器作为最后一个参数。例如:
template<class ForwardIt, class UnaryPredicate, class Generator>
void my_replace_if(ForwardIt first, ForwardIt last,
UnaryPredicate p, Generator g)
{
for (; first != last; ++first) {
if(p(*first)) {
*first = g();
}
}
}
bool IsOdd (int i) { return ((i%2)==1); }
int main(int argc, const char * argv[]) {
std::vector<int> foo{1,2,3,4,5,6,7};
std::vector<int> bar{10,20,30,40,50,60,70};
int i = 0;
my_replace_if (foo.begin(), foo.end(), IsOdd, [&bar, &i]()
{
return bar[i++];
});
for (auto el : foo)
{
std::cout << el << std::endl;
}
return 0;
}
===== 编辑 =====
正如 anastaciu 所指出的,生成器的索引应该随着每个步骤递增,而不仅仅是在调用生成器时。
例如:
my_replace_if (foo.begin(), foo.end(),
[&i](int v) { i++; return ((v%2)==1); },
[&bar, &i]() { return bar[i-1]; });
不过老实说,这种情况真的有点过分了,而且看起来也不好看。
你可以利用 std::transform
:
std::vector<int> result;
std::transform(
foo.begin(), foo.end(), bar.begin(),
std::back_inserter(result),
[](const auto& a, const auto& b) {
if (a % 2 == 0) {
return a;
}
return b;
}
);
您可以使用带有两个输入迭代器范围的 std::transform
重载:
std::transform(foo.begin(), foo.end(), bar.begin(), foo.begin(),
[](auto const& a, auto const& b) {
if (a % 2)
return b;
return a;
}
);
添加到此处的答案,您可以创建自己的函数:
演示:https://godbolt.org/z/yf3jYx
void IsOdd (const std::vector<int>& a, std::vector<int>& b) {
for(size_t i = 0; i < a.size() && i < b.size(); i++){
if(b[i] % 2 == 1)
b[i] = a[i];
}
}
并在 main 中调用它:
IsOdd(bar, foo);
给定以下向量:
std::vector<int> foo{1,2,3,4,5,6,7};
std::vector<int> bar{10,20,30,40,50,60,70};
最后我希望 foo
包含值 { 10, 2, 30, 4, 50, 6, 70 }
意味着替换所有奇数。
我试过算法std::replace_if,但是如何获取柱对应的值?
// replace_copy_if example
#include <iostream> // std::cout
#include <algorithm> // std::replace_copy_if
#include <vector> // std::vector
bool IsOdd (int i) { return ((i%2)==1); }
int main () {
std::vector<int> foo{1,2,3,4,5,6,7};
std::vector<int> bar{10,20,30,40,50,60,70};
std::replace_if (foo.begin(), foo.end(), IsOdd, 0);
std::cout << "foo contains:";
for (auto i: foo){ std::cout << ' ' << i; }
std::cout << '\n';
return 0;
}
// output : foo contains: 0 2 0 4 0 6 0
// desired output : foo contains: 10 2 30 4 50 6 70
// replace_copy_if example
#include <iostream> // std::cout
#include <vector> // std::vector
int main () {
std::vector<int> foo{1,2,3,4,5,6,7};
std::vector<int> bar{10,20,30,40,50,60,70};
for (size_t i = 0; i < bar.size(); i++)
{
if (foo[i]%2==1) foo[i]=bar[i];
}
std::cout << "bar contains:";
for (auto i: foo){ std::cout << ' ' << i; }
std::cout << '\n';
return 0;
}
std::replace_if
仅支持用指定为最后一个参数的常量值替换元素。但是,如果您觉得它对您有意义,您可以基于 reference implementation 编写自己的 replace_if
函数,并使其接受某种生成器作为最后一个参数。例如:
template<class ForwardIt, class UnaryPredicate, class Generator>
void my_replace_if(ForwardIt first, ForwardIt last,
UnaryPredicate p, Generator g)
{
for (; first != last; ++first) {
if(p(*first)) {
*first = g();
}
}
}
bool IsOdd (int i) { return ((i%2)==1); }
int main(int argc, const char * argv[]) {
std::vector<int> foo{1,2,3,4,5,6,7};
std::vector<int> bar{10,20,30,40,50,60,70};
int i = 0;
my_replace_if (foo.begin(), foo.end(), IsOdd, [&bar, &i]()
{
return bar[i++];
});
for (auto el : foo)
{
std::cout << el << std::endl;
}
return 0;
}
===== 编辑 =====
正如 anastaciu 所指出的,生成器的索引应该随着每个步骤递增,而不仅仅是在调用生成器时。
例如:
my_replace_if (foo.begin(), foo.end(),
[&i](int v) { i++; return ((v%2)==1); },
[&bar, &i]() { return bar[i-1]; });
不过老实说,这种情况真的有点过分了,而且看起来也不好看。
你可以利用 std::transform
:
std::vector<int> result;
std::transform(
foo.begin(), foo.end(), bar.begin(),
std::back_inserter(result),
[](const auto& a, const auto& b) {
if (a % 2 == 0) {
return a;
}
return b;
}
);
您可以使用带有两个输入迭代器范围的 std::transform
重载:
std::transform(foo.begin(), foo.end(), bar.begin(), foo.begin(),
[](auto const& a, auto const& b) {
if (a % 2)
return b;
return a;
}
);
添加到此处的答案,您可以创建自己的函数:
演示:https://godbolt.org/z/yf3jYx
void IsOdd (const std::vector<int>& a, std::vector<int>& b) {
for(size_t i = 0; i < a.size() && i < b.size(); i++){
if(b[i] % 2 == 1)
b[i] = a[i];
}
}
并在 main 中调用它:
IsOdd(bar, foo);