C++ 实现 map-reduce 操作

C++ 实现 map-reduce 操作

引言

在函数式编程中,map、reduce、filter 这三种对容器的操作十分方便,Python 内置函数就直接提供了上述操作;

虽然 C++ 标准库中没有直接提供上述三种操作,但借助标准库可非常容易地实现,并且通过模板可支持多种容器;

代码实现

/**
 * *****************************************************************************
 * @file mymapreduce.hpp
 */
#include <algorithm>

namespace MyMapReduce {
/**
 * @brief  映射操作
 * @param  in  - 输入容器
 * @param  op  - 一元运算
 * @return out - 输出容器
 */
template<typename Container, typename UnaryOperation>
Container map(const Container & in, UnaryOperation op)
{
    Container out(in.size());
    std::transform(in.cbegin(), in.cend(), out.begin(), op);
    return out;
}

/**
 * @brief  规约操作
 * @param  in  - 输入容器
 * @param  op  - 二元运算
 * @return ret - 输出结果
 */
template<typename Container, typename BinaryOperation>
typename Container::value_type reduce(const Container & in, BinaryOperation op)
{
    typename Container::value_type ret = *in.cbegin();
    for (auto itr = in.cbegin() + 1; itr != in.cend(); ++itr) {
        ret = op(ret, *itr);
    }
    return ret;
}

/**
 * @brief  过滤操作
 * @param  in   - 输入容器
 * @param  pred - 一元谓词
 * @return out  - 输出容器
 */
template<typename Container, typename UnaryPredicate>
Container filter(const Container & in, UnaryPredicate pred)
{
    Container out;
    std::copy_if(in.cbegin(), in.cend(), std::back_inserter(out), pred);
    return out;
}
} // namespace MyMapReduce

测试案例

/**
 * *****************************************************************************
 * @file main.cpp
 */
#include <vector>
#include <iostream>
#include "mymapreduce.hpp"

int main()
{
    std::vector<double> vec = {1, 2, 3, 4, 5, 6};
    
    auto printVec = [](const std::vector<double>& vec) {
        for (const double ele : vec) {
            std::cout << ele << "  ";
        }
        std::cout << '\n';
    };

    std::vector<double> vec2 = MyMapReduce::map(vec, 
                                                [](const double x) -> double { return x * x; });
    double ret = MyMapReduce::reduce(vec, 
                                     [](const double x, const double y) -> double { return x + y; });
    std::vector<double> vec3 = MyMapReduce::filter(vec, 
                                                   [](const double x) -> bool {return x>3;});
    
    printVec(vec2);    // 1  4  9  16  25  36
    printVec({ret});   // 21 
    printVec(vec3);    // 4  5  6 
    
    return 0;
}

参考

Python函数式编程map()、filter()和reduce()

https://github.com/DragonFive/cpp11


本文作者: 王同学