map、reduce、lambda能做神马?

来源:互联网 发布:软件测试职业资格证书 编辑:程序博客网 时间:2024/05/17 05:57

据wiki(http://zh.wikipedia.org/wiki/MapReduce)记载“MapReduce是Google提出的一个软件架构,用于大规模数据集(大于1TB)的并行运算。概念“Map(映射)”和“Reduce(化简)”,及他们的主要思想,都是从函数式编程语言借来的,还有从矢量编程语言借来的特性。当前的软件实现是指定一个Map(映射)函数,用来把一组键值对映射成一组新的键值对,指定并发的Reduce(化简)函数,用来保证所有映射的键值对中的每一个共享相同的键组。”(google的报告在这里http://research.google.com/archive/mapreduce.html)。

这段话说的有点抽象,我们可以简略的理解为map是对一组数据做相同的操作,比如对一个一维数组的每一项加一;而reduce是把一组数据用相同的规则合并,比如把求一维数组的各项和就是每一项的值都加起来。

说到map、reduce就不得不提lambda,这个是用来定义匿名函数的,比如“lambda x,y:x+y”就定义了一个函数,返回值是输入的两个参数值的和。

下面我们用一个具体例子来实验一下reduce:

reduce(lambda x,y:x*y, xrange(1,10+1), 1)

返回的结果是3628800,即10!。可以看到,reduce把[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]的每一项都应用了乘积,于是就得到了10的阶乘。

下面加进map,求10以内自然数的平方和:

reduce(lambda x,y:x+y, map(lambda x:x*x,xrange(1,10+1)), 0)

上边这一行中,首先用 map(lambda x:x*x,xrange(1,10+1))求出了“10以内自然数的平方”即[1, 4, 9, 16, 25, 36, 49, 64, 81, 100],然后用reduce把每一项加起来,由于这次是求和,那么初始值,也就是reduce的最后一个参数,就应该是0。

需要说明的是,python还支持这样的用法“[x*x for x in xrange(1,10+1)]”来获得“10以内自然数的平方”,这样可以用“reduce(lambda x,y:x+y, [x*x for x in xrange(1,10+1)], 0)”同样获得385的正确结果。

使用for的形式代替map还有一个好处,就是免去了使用filter的步骤。比如,如果只需要“10以内偶数的平方”,就可以用“[x*x for x in xrange(1,10+1) if x%2==0]”来完成。

看过上边这絮絮叨叨一大堆,估计您已经对这种折腾python的方式有点儿适应了吧?下面就是“将一个正整数转换成二进制数的字符串”的一种解法:

reduce(lambda x,y:(str(x[1]%2)+x[0],x[1]>>1) if x[1]>0 else x, xrange(len(str(N))*3.321928095+2), ('',N))[0]

解释一下3.321928095,其实就是math.log(10,2)。因为无论是map还是reduce,虽然功能强大,但是无法控制迭代项的数量,这一点虽然影响了一行写出python程序,但是也是有办法解决的。至于怎么解决,还请您继续关注后续博文。

0 0
原创粉丝点击