当前位置: 首页 > Linux

如何减少列表的维度?sum()函数的妙用

时间:2023-04-06 21:03:09 Linux

上个月学习组的同学S问了一道题,可以理解为列表降维。例子如下:oldlist=[[1,2,3],[4,5]]#想得到结果:newlist=[1,2,3,4,5]原始数据是一个二-维列表,目的是获取列表中所有元素的具体值。从抽象的角度来看,也可以看作是列表解压或者列表降维。这道题不难,但是怎么写更优雅呢?#方法一,粗拼接法:newlist=oldlist[0]+oldlist[1]这种方法简单粗暴。如果您需要拼接任何内容,只需将其取出并直接拼接即可。但是,如果原始列表有很多子列表,这种方法就会变得很麻烦。把原问题升级一下:一个二维列表包含n个一维列表元素,如何优雅地将这些子列表组装成一个新的一维列表?方法1需要编写n个对象和n-1个连接操作。当然不是。我们来看看方法二:#方法二,列表理解:newlist=[iforjinrange(len(oldlist))foriinoldlist[j]]这个表达式中有两个for语句,在第一个中第一个for语句,我们先取出原列表的长度,然后构造range对象。此时j的取值范围为[0,n-1]的闭区间。在第二个for语句中,oldlist[j]引用了原list的第j个子列表,foriinoldlist[j]会遍历并提取j子列表的元素,因为j的取值范围对应了所有的索引值原来的列表,所以问题的解决最终实现了。这种方法足够优雅并且不太难理解。然而,我们能满足于此吗?还有其他技巧吗,哦不,其他高级方法吗?F同学贡献了一个思路:#方法三,巧用sum:newlist=sum(oldlist,[])说实话,这个方法让我很意外!sum()函数不是求和的吗?怎么会有这种用法呢?这种写法是利用什么原理?由于一开始不知道sum()函数可以接受两个参数,也不知道它们是如何用于计算的,所以一时糊涂了。然而,当我知道sum()的完整用法时,我恍然大悟。我就不保密了,直接揭穿吧。语法:sum(iterable[,start])sum()函数的第一个参数是一个可迭代的对象,比如列表、元组或集合等,第二个参数是起始值,即0默认。它的目的是根据起始值“添加”到可迭代对象的所有元素。上面的例子,执行效果是将oldlist中的sublists一个一个的添加到第二个参数中,lists的添加相当于extend操作,所以最终的结果是一个被[]扩展的list。这里有两个关键点:sum()函数允许有两个参数,第二个参数是起点。可能sum()函数更多的是用于数值求和,但是用于列表求和时却有奇效。它比列表理解更优雅和简洁!至此,之前升级版的问题已经得到很好的解答。简单回顾一下,原来学生的问题可以用三种方法解决,第一种方法中规中矩,第二种方法先进,第三种方法异端(没有贬义,只是说出乎意料,但是效果惊人)。这不是一个很难的问题,但是经过大家的讨论和分享,其实也衍生出了有价值的学习内容。前不久也是群里的一道题,也产生了同样的学习效果,详见《Python进阶:如何将字符串常量转为变量?》。我从中得到一个启示:我们应该从多个角度去思考问题,努力寻找更好的解决方案。同时,要牢牢掌握基础知识,灵活运用。学无止境,在这里我想敞开心扉,看看我能发现什么。1、如果原列表的元素有除列表之外的其他类型的元素,如何将同类元素合并在一起?2、如果是三维或者更高维的列表,如何更好的将它们压缩成一维的列表?3.sum()函数的要点是什么?前两个问题增加了复杂度,似乎没有什么“灵丹妙药”可以解决。只能用笨办法一个一个拆解解压。第三个思考问题是关于sum()函数本身的用法。看看官方文档是怎么说的:iterable的项一般都是数字,起始值不允许是字符串。对于某些用例,sum()有很好的替代方法。连接字符串序列的首选、快速方法是调用''.join(sequence)。要添加具有扩展精度的浮点值,请参阅math.fsum()。要连接一系列可迭代对象,请考虑使用itertools.chain().sum()第二个参数不允许是字符串。如果使用,会报错:TypeError:sum()can'tsumstrings[use''.join(seq)instead]为什么不推荐使用sum()来拼接字符串?哈哈,文档推荐使用join()方法,因为它更快。为了不让我们使用slow方法,特意不允许sum()的第二个参数为字符串。文档还建议在某些使用场景下不要使用sum(),例如对扩展精度的浮点数求和时,建议使用math.fsum();在拼接一系列可迭代对象时,应该考虑使用itertools。链()。浮点数的计算是一个难题。转载了一篇文章《如何在 Python 里面精确四舍五入?》,里面有精彩的分析。而itertools.chain()可以将不同类型的可迭代对象串联成一个更大的迭代器,这在老文《Python进阶:设计模式之迭代器模式》中也有讨论。不经意间,对sum()函数的考虑其实连接了Python的其他进阶内容。一个小小的功能,却成了学习路上的一个枢纽。前段时间还写了range()、locals()、eval()等内置函数,也是通过一个问题点涉及到多个知识点,受益匪浅。这些内置函数/类的魔力着实不小。本文到此结束,希望对你有所帮助。友情提示:本次公众号限时抽奖活动将送出《Python数据分析与挖掘实战》、《Python语言程序设计》《自学Python编程基础、科学计算及数据分析》《实用机器学习》、《Python程序员面试算法宝典》等15本Python书籍,活动截止时间为本月20日18:00。赶快画画吧!详情请点击:抽奖送书公众号【Python猫】,专注于Python技术、数据科学和深度学习,力图打造一个有趣好用的学习分享平台。本期连载系列精品文章,包括喵星哲学猫系列、Python进阶系列、好书推荐系列、优质英文推荐与翻译等,欢迎关注。PS:后台回复“爱学习”,即可免费获得学习大礼包。