用c++理解python的reduce函数

     作为对一个平时靠c++吃饭的程序员来说,偶尔也想写点python程序,要想写就得要学,要学就得要总结和关联,把要学的知识与已学的知识相关联起来,可以更快地学习和理解新的知识。

    首先看一下reduce()函数吧,http://www.cnblogs.com/lonkiss/p/understanding-python-reduce-function.html 有对reduce()函数的详细介绍和使用说明,下面的python代码都是参考的这个页面上的。

      reduce() 函数在 python 2 是内置函数, 从python 3 开始移到了 functools 模块。

官方文档是这样介绍的

reduce(...)
reduce(function, sequence[, initial]) -> value

Apply a function of two arguments cumulatively to the items of a sequence,
from left to right, so as to reduce the sequence to a single value.
For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates
((((1+2)+3)+4)+5). If initial is present, it is placed before the items
of the sequence in the calculation, and serves as a default when the
sequence is empty.

从左到右对一个序列的项累计地应用有两个参数的函数,以此合并序列到一个单一值。

例如,reduce(lambda x, y: x+y, [1, 2, 3, 4, 5])  计算的就是((((1+2)+3)+4)+5)。

如果提供了 initial 参数,计算时它将被放在序列的所有项前面,如果序列是空的,它也就是计算的默认结果值了

      浓浓的熟悉味道,这不就是c++ stl里面的std::accumulate嘛,先写一段简单的代码看一下两者的对比。 

先是python的:

def add(x, y):
    return x+y

from functools import reduce
reduce(add, [1,2,3,4])

输出结果是10

看看c++的

int n[]={1, 2, 3, 4};
std::cout << std::accumulate(n, n+4, 0) << std::endl;

没有意外,也是10

       其实这个例子并不好,因为在python中单纯的序列累加可以使用内置函数sum,而没有运算函数作为参数的std::accumulate函数也是完成的容器内元素的累加,从这一点上来说,不带运算函数参数的std::accumulate对应的应该是sum函数。

print(sum([1, 2, ,3 ,4]))

      看一下std::accumulate的原型,有2个:

sum (1)
template <class InputIterator, class T>
   T accumulate (InputIterator first, InputIterator last, T init);
custom (2)
template <class InputIterator, class T, class BinaryOperation>
   T accumulate (InputIterator first, InputIterator last, T init,
                 BinaryOperation binary_op);

       

很明显,sum函数对应的是第一个,reduce函数对应的是第二个。

来点复杂一点的分类,看一下reduce函数和std::accumulate函数是如何对应的,这里是按性别分类,程序只是演示用,python的:

from functools import reduce
scientists =({'name':'Alan Turing', 'age':105, 'gender':'male'},
             {'name':'Dennis Ritchie', 'age':76, 'gender':'male'},
             {'name':'Ada Lovelace', 'age':202, 'gender':'female'},
             {'name':'Frances E. Allen', 'age':84, 'gender':'female'})
def group_by_gender(accumulator , value):
    accumulator[value['gender']].append(value['name'])
    return accumulator
grouped = reduce(group_by_gender, scientists, {'male':[], 'female':[]})
print(grouped)

输出:

{'male': ['Alan Turing', 'Dennis Ritchie'], 'female': ['Ada Lovelace', 'Frances E. Allen']}

用c++来模拟一下,好像不太好模拟,姑且这样吧

    std::vector<std::map<std::string, std::string>> data = {
        {{"name", "Alan Turing"}, {"gender", "male"}},
        {{"name", "Dennis Ritchie"}, {"gender", "male"}},
        {{"name", "Ada Lovelace"}, {"gender", "female"}},
        {{"name", "Frances E. Allen"}, {"gender", "female"}}
    };
    
    std::map<std::string, std::vector<std::string>> output;
    output = std::accumulate(data.begin(), data.end(), output,
        [](std::map<std::string, std::vector<std::string>>& item1, std::map<std::string, std::string>& item2) -> std::map<std::string, std::vector<std::string>>& {
                item1[item2["gender"]].push_back(item2["name"]);
                return item1;
            });
    
    for (auto& val : output) {
        std::cout << val.first << std::endl;
        for (auto& str : val.second) {
            std::cout << str << std::endl;
        }
    }

输出:

female

Ada Lovelace

Frances E. Allen

male

Alan Turing

Dennis Ritchie

    这不,会了一个就会第二个了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值