【问题标题】:How to replicate map, filter and reduce behaviors in C++ using STL?如何使用 STL 在 C++ 中复制映射、过滤和减少行为?
【发布时间】:2017-04-15 13:24:04
【问题描述】:

我想我们可以像这样使用 std::transform 在 C++ 中复制地图行为:

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

std::transform(in.being() , 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++ 黑客什么是做 X 的“更好的方法”,你会得到三个不同的答案。
  • “过滤器”可能对应于std::copy_if 和/或std::remove_if。我不确定“减少”应该做什么。
  • @SamVarshavchik 哈哈。你觉得什么更好?有第三种方法吗?这些对我来说都是非常有趣的问题。
  • @IgorTandetnik:reduce/fold 在 C++ 中被称为 std::accumulate
  • transform, copy_if, accumulate.

标签: c++ c++11 stl functional-programming


【解决方案1】:

取决于您使用的容器。

std::back_inserter 仅在容器具有push_back 函数时才有效。

例如back_insterter 不能与forward_list 一起使用。

在这种情况下,我们需要在调用 std::transform 之前分配内存,并且第一种方法更好。

【讨论】:

    【解决方案2】:

    你可以用std::transform做映射,std::copy_if做过滤。

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


    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
    

    【讨论】:

      猜你喜欢
      • 2021-05-21
      • 2016-01-18
      • 2020-05-07
      • 2016-06-28
      • 1970-01-01
      • 2023-04-03
      • 1970-01-01
      • 2013-07-15
      • 2011-05-29
      相关资源
      最近更新 更多