【问题标题】:How to combine std::copy_if and std::transform?如何结合 std::copy_if 和 std::transform?
【发布时间】:2018-09-19 07:47:45
【问题描述】:

考虑这段代码 sn-p :迭代第一种类型 T1 的一个容器,以创建第二种类型 T2 的第二个容器,应用转换函数 T1->T2 但仅用于验证谓词的 T1 元素 (T1 -> bool )

(在以下示例中为奇数)。

std::vector<int> myIntVector;
myIntVector.push_back(10);
myIntVector.push_back(15);
myIntVector.push_back(30);
myIntVector.push_back(13);

std::vector<std::string> myStringVectorOfOdd;

std::for_each(myIntVector.begin(), myIntVector.end(),
    [&myStringVectorOfOdd](int val)
{
    if (val % 2 != 0)
        myStringVectorOfOdd.push_back(std::to_string(val));

});

我不喜欢这段代码中的 lambda 捕获。有没有办法结合 std::copy_if 和 std::transform 以更优雅和简洁的方式实现相同的结果?

【问题讨论】:

  • 你为什么不喜欢捕获?您将其捕获为参考并将您的元素推到它上面。我不确定这有什么不足。诚然,这不是 Python 的漂亮 myStringVectorOfOdd = [str(x) for x in myIntVector) if x % 2 == 1],但也不是糟糕。

标签: c++ std


【解决方案1】:

这是一个transform_if 模板,它采用通常的输入迭代器对、一个输出迭代器和一个谓词以及一个转换函数对象。

template <class InputIt, class OutputIt, class Pred, class Fct>
void transform_if(InputIt first, InputIt last, OutputIt dest, Pred pred, Fct transform)
{
   while (first != last) {
      if (pred(*first))
         *dest++ = transform(*first);

      ++first;
   }
}

您可以将它用于您的示例,如下所示。

transform_if(myIntVector.cbegin(), myIntVector.cend(),
    std::back_inserter(myStringVectorOfOdd),
    [](int n){ return n % 2 != 0; },
    [](int n){ return std::to_string(n); });

它不是超级简洁,但过滤和转换被很好地分离为无捕获的 lambda,并且算法本身惯用地适用于迭代器。

由于范围库为组合算法提供了更好的支持,这里也是基于Boost range

#include <boost/range/algorithm.hpp>
#include <boost/range/adaptors.hpp>

using boost::adaptors::filtered;

boost::transform(myIntVector | filtered([](int n){ return n % 2 != 0; }),
    std::back_inserter(myStringVectorOfOdd), [](int n){ return std::to_string(n); });

【讨论】:

    【解决方案2】:

    使用range-v3,它将是:

    const std::vector<int> myIntVector {10, 15, 30, 13};
    
    std::vector<std::string> myStringVectorOfOdd = myIntVector
        | ranges::view::filter([](int i){ return i % 2 != 0; })
        | ranges::view::transform([](int i){ return std::to_string(i); });
    

    Demo

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-04-24
      • 2014-04-26
      • 1970-01-01
      • 2012-10-27
      • 2016-08-29
      • 2016-04-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多