【问题标题】:replace all odd values in vector with coresponing value from new vector用新向量中的对应值替换向量中的所有奇数值
【发布时间】:2020-06-03 13:59:56
【问题描述】:

给定以下向量:

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算法,但是如何获取bar对应的值呢?

// 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

【问题讨论】:

  • 如果两个数组的大小不同怎么办?
  • 好点。在我的具体情况下,它会事先检查,因为数据会损坏
  • 所以你想替换foo中的值但是你测试打印bar,这是怎么回事?
  • 修复了代码中的问题,它与描述匹配

标签: c++ algorithm c++11 vector stdvector


【解决方案1】:
// 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;
}

【讨论】:

  • anastaciu,这个代码怎么会替换偶数?你读过这个问题吗? @aleem md,您可以使用“if (foo[i]%2)”而不是“if (foo[i]%2==1)”。代码一开始就要检查两个数组的长度,否则可能会导致意想不到的结果。
【解决方案2】:

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]; });

但老实说,在这种情况下,它确实有点矫枉过正,甚至看起来都不好看。

【讨论】:

  • 这个输出10 2 20 4 30 6 40
  • 像这种方法一样,对于我的具体情况来说有点过头了,因为它只使用一次
【解决方案3】:

您可以使用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;
    }
);

Demo

【讨论】:

    【解决方案4】:

    您可以使用采用两个输入迭代器范围的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; 
      }
    );
    

    【讨论】:

    • 三元组会使 lambda 的代码更短,恕我直言,更清晰:返回 a%2 ? b : 一个
    • @UriRaz 是的,为了简洁起见,我确实考虑过使用 三元运算符 的选项(即return (a%2)? b: a;,单个return 语句)在 lambda 表达式的主体中。但是,我认为这可能会妨碍可读性。
    【解决方案5】:

    在此处添加答案,您可以创建自己的功能:

    演示: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);
    

    【讨论】:

    • 问题说 - “最后我希望“ foo ”包含值 { 10, 2, 30, 4, 50, 6, 70 } 意味着替换所有奇数值。”你用“a”替换“b”意味着“bar”用“foo”。
    • @ManojBanik,确实如此,打印的矢量是 bar 的事实让我失望。
    • @ManojBanik,当你指出我的错误时,我做到了,只是忘记更改输出文本。感谢您调试我的代码,;)
    猜你喜欢
    • 2020-10-02
    • 2019-12-14
    • 1970-01-01
    • 1970-01-01
    • 2015-07-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-31
    相关资源
    最近更新 更多