如何结合 std::copy_if 和 std::transform? [英] How to combine std::copy_if and std::transform?

查看:41
本文介绍了如何结合 std::copy_if 和 std::transform?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

consider this code snippet : iteration over one container of a first type T1 for creating a second container of a second type T2 applying a transformation function T1->T2 but only for T1 elements verifying a predicate (T1 -> bool )

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

(is Odd in the following example).

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 以更优雅和简洁的方式实现相同的结果?

What I don't like in this code is the capture on the lambda. Is there a way to combine std::copy_if and std::transform to achieve the same result in a more elegant and concise way ?

推荐答案

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

Here is a transform_if template that takes the usual input iterator pair, an output iterator and a predicate as well as a transformation function object.

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

您可以将其用于您的示例,如下所示.

You can use it for your example like the following.

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

它不是非常简洁,但过滤和转换很好地分离到无捕获的 lambda 表达式中,并且算法本身在迭代器上是惯用的.

It's not super concise, but filtering and transformation are well separated into to capture-free lambdas, and the algorithm itself idiomatically works on iterators.

由于范围库为组合算法提供了更好的支持,这里基于 提升范围:

As range libraries offer better support for composing algorithms, here is the same based on 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); });

这篇关于如何结合 std::copy_if 和 std::transform?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆