设为首页 收藏本站
查看: 951|回复: 0

[经验分享] Python----reduce原来是这样用的

[复制链接]

尚未签到

发表于 2015-4-21 11:11:43 | 显示全部楼层 |阅读模式
  官方解释:
  Apply function of two arguments cumulatively to the items of iterable, from left to right, so as to reduce the iterable to a single value. For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates ((((1+2)+3)+4)+5). The left argument, x, is the accumulated value and the right argument, y, is the update value from the iterable. If the optional initializer is present, it is placed before the items of the iterable in the calculation, and serves as a default when the iterable is empty. If initializer is not given and iterable contains only one item, the first item is returned. Roughly equivalent to:
  意思就是说:将一个可迭代的对象应用到一个带有两个参数的方法上,我们称之为appFun,遍历这个可迭代对象,将其中的元素依次作为appFun的参数,但这个函数有两个参数,作为哪个参数呢?有这样的规则,看一下下面reduce方法的实现,有三个参数,第一个参数就是上面说的appFun,第二个参数就是那个可迭代的对象,而第三个呢?当调用reduce方法的时候给出了initializer这个参数,那么第一次调用appFun的时候这个参数值就作为第一个参数,而可迭代对象的元素依次作为appFun的第二个参数;如果调用reduce的时候没有给出initializer这个参数,那么第一次调用appFun的时候,可迭代对象的第一个元素就作为appFun的第一个元素,而可迭代器的从第二个元素到最后依次作为appFun的第二个参数,除第一次调用之外,appFun的第一个参数就是appFun的返回值了。例如reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]),计算1到5的和,因为没有给定initializer参数,所以第一次调用x+y时,x=1,即列表的第一个元素,y=2,即列表的第二个元素,之后返回的1+2的结果作为第二次调用x+y中的x,即上一次的结果,y=2,即第二个元素,依次类推,知道得到1+2+3+4+5的结果。
  这样看来,其实下面的代码定义是有一点问题,我们在程序中调用这段代码reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]),得到的结果为16,而正确的结果为15,问题在于如果集合不是以0开始,那么按照如下代码,第一次调用x=1,即第一个元素,y也是等于1,也是第一个元素,而正确的y应该是2。所以真正的reduce方法应该和下面的例子是有差别的。



def reduce(function, iterable, initializer=None):
it = iter(iterable)
if initializer is None:
try:
initializer = next(it)
except StopIteration:
raise TypeError('reduce() of empty sequence with no initial value')
accum_value = initializer
for x in iterable:
accum_value = function(accum_value, x)
return accum_value
  那么reduce函数能做什么,什么情况下要用reduce呢,看下面的例子:
  例如上面的例子,实现一个整形集合的累加。假设lst = [1,2,3,4,5],实现累加的方式有很多:
  第一种:用sum函数。



sum(lst)
  第二种:循环方式。



def customer_sum(lst):
result = 0
for x in lst:
result+=x
return result
#或者
def customer_sum(lst):
result = 0
while lst:
temp = lst.pop(0)
result+=temp
return result
if __name__=="__main__":
lst = [1,2,3,4,5]
print customer_sum(lst)

  第三种:递推求和



def add(lst,result):
if lst:
temp = lst.pop(0)
temp+=result
return add(lst,temp)
else:
return result
if __name__=="__main__":
lst = [1,2,3,4,5]
print add(lst,0)
  第四种:reduce方式



lst = [1,2,3,4,5]
print reduce(lambda x,y:x+y,lst)
#这种方式用lambda表示当做参数,因为没有提供reduce的第三个参数,所以第一次执行时x=1,y=2,第二次x=1+2,y=3,即列表的第三个元素

#或者
lst = [1,2,3,4,5]
print reduce(lambda x,y:x+y,lst,0)
#这种方式用lambda表示当做参数,因为指定了reduce的第三个参数为0,所以第一次执行时x=0,y=1,第二次x=0+1,y=2,即列表的第二个元素,
假定指定reduce的第三个参数为100,那么第一次执行x=100,y仍然是遍历列表的元素,最后得到的结果为115

#或者
def add(x,y):
return x+y
print reduce(add, lst)
#与方式1相同,只不过把lambda表达式换成了自定义函数
#或者
def add(x,y):
return x+y
print reduce(add, lst,0)
#与方式2相同,只不过把lambda表达式换成了自定义函数
  再举一个例子:有一个序列集合,例如[1,1,2,3,2,3,3,5,6,7,7,6,5,5,5],统计这个集合所有键的重复个数,例如1出现了两次,2出现了两次等。大致的思路就是用字典存储,元素就是字典的key,出现的次数就是字典的value。方法依然很多
  第一种:for循环判断



def statistics(lst):
dic = {}
for k in lst:
if not k in dic:
dic[k] = 1
else:
dic[k] +=1
return dic
lst = [1,1,2,3,2,3,3,5,6,7,7,6,5,5,5]
print(statistics(lst))
  第二种:比较取巧的,先把列表用set方式去重,然后用列表的count方法



def statistics2(lst):
m = set(lst)
dic = {}
for x in m:
dic[x] = lst.count(x)
return dic
lst = [1,1,2,3,2,3,3,5,6,7,7,6,5,5,5]
print statistics2(lst)
  第三种:用reduce方式



def statistics(dic,k):
if not k in dic:
dic[k] = 1
else:
dic[k] +=1
return dic
lst = [1,1,2,3,2,3,3,5,6,7,7,6,5,5,5]
print reduce(statistics,lst,{})  
#提供第三个参数,第一次,初始字典为空,作为statistics的第一个参数,然后遍历lst,作为第二个参数,然后将返回的字典集合作为下一次的第一个参数
或者
d = {}
d.extend(lst)
print reduce(statistics,d)
#不提供第三个参数,但是要在保证集合的第一个元素是一个字典对象,作为statistics的第一个参数,遍历集合依次作为第二个参数
  通过上面的例子发现,凡是要对一个集合进行操作的,并且要有一个统计结果的,能够用循环或者递归方式解决的问题,一般情况下都可以用reduce方式实现。
  reduce函数真是“一位好同志啊”!

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-59185-1-1.html 上篇帖子: 一人一python挑战题解 下篇帖子: PyCharm
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表