如何使用 STL 复制 C++ 中的映射、过滤和归约行为?

问题描述 投票:0回答:3

我想我们可以使用 std::transform 来复制 C++ 中的映射行为,如下所示:

std::vector<int> in = { 1 , 2 , 3 ,4 }; 
std::vector<int> out(in.size()); 

std::transform(in.begin() , in.end() , out.begin() , [](const int & val)
{
    return val+1;
});

我想更好的方法是使用背面插入器。'

std::vector<int> out2;

std::transform(in.begin() , in.end() , std::back_inserter(out2) , [](const int & val){
      return val + 1;
});

// out will be { 2 , 3 ,4 ,5 }

我说得对吗?如何使用 STL 在 C++ 中进行过滤和归约操作?

c++ c++11 stl functional-programming
3个回答
57
投票

您可以使用

std::transform
进行映射,使用
std::copy_if
进行过滤。

根据您的输入以及是否要使用特定类型的执行模型,您有两种减少选项。我在下面编写了一些简单的示例来演示常见用例。请注意,所有这些算法都有多个重载,您应该根据您的需要使用。


  1. std::transform

对整数向量进行平方:

std::vector<int> nums{1,2,3,4};
auto unary_op = [](int num) {return std::pow(num, 2);};
std::transform(nums.begin(), nums.end(), nums.begin(), unary_op);
// nums: 1, 4, 9, 16
  1. std::copy_if

仅从整数向量中过滤奇数:

std::vector<int> nums{1,2,3,4};
std::vector<int> odd_nums;
auto pred = [](int num) {return num & 1;};
std::copy_if(nums.begin(), nums.end(), std::back_inserter(odd_nums), pred);
// odd_nums: 1, 3
  1. std::reduce

使用并行执行模型对向量中从 0 开始的整数求和。例如,如果您要对一个非常大的列表执行归约操作,这非常有用。认为本例中的二元运算符(“+”)是关联且可交换的,否则行为将是不确定的。这真的很重要。如果执行模型不是顺序的,则reduce操作是无序的。仅自 C++17 起可用。

std::vector<int> nums{1,2,3,4};
auto binary_op = [](int num1, int num2){return num1 + num2;};
int result = std::reduce(std::execution::par, nums.begin(), nums.end(), 0, binary_op);
// result: 10
  1. std::accumulate

与reduce相同,只是不支持执行模型并且reduce操作是按顺序完成的。

std::vector<int> nums{1,2,3,4};
auto binary_op = [](int num1, int num2){return num1 + num2;};
int result = std::accumulate(nums.begin(), nums.end(), 0, binary_op);
// result: 10

3
投票

取决于您使用哪个容器。

仅当容器具有

std::back_inserter

 功能时,
push_back
才会起作用。

例如

back_insterter
不能与
forward_list
一起使用。

在这种情况下,我们需要在调用

std::transform
之前分配内存,并且第一种方法更好。


1
投票

我将

happy_sisyphus 的答案
中的 transform 示例概括为一个函数:

#include <algorithm>

// avoid calling this function 'map', it will clash with 'using std::map;'
template<typename I, typename F>
void apply_to_all(I& iterable, const F& functor)
{
    std::transform(iterable.begin(), iterable.end(), iterable.begin(), functor);
}

使用示例:

std::vector<int> nums{1,2,3,4};
auto unary_op = [](int num) {return std::pow(num, 2);};

apply_to_all(nums, unary_op);
// nums: 1, 4, 9, 16
© www.soinside.com 2019 - 2024. All rights reserved.