
刚开始学习的那个时候, 一旦手里拿到了一串数据, 我的条件反射便是去写一个for循环, 并且在这个for循环里面还需要加上几个if语句, 吭哧吭哧地写上十几行代码才能够把活给干完。后来才了解到, 其实早就在内置函数里给我们准备好了“数据处理四件套”——map、、、。同样的一个需求, 可是别人仅仅用两行代码就能够搞定, 而我写了二十行代码, 纯粹属于费力不不讨好、毫无成效却又毫无益处地做了这件事。今儿就把这四件套一回讲明白。你只需记着一个景象: 把数据设想成流水生产线上的一批货物, 四个函数便是四个各异的“车间”。第一个车间map批量加工厂map所做之事极为纯粹, 针对一组数据当中的每一个单独元素, 进行共同且一致的同一道加工处理, 随后吐露出一组崭新的数据。最为奇妙的是, 它仅仅操作“出厂件”, 绝不触碰你的“原件”。nums [10, 20, 30, 40] result list(map(lambda x: x * 2, nums)) print(result) # [20, 40, 60, 80] print(nums) # [10, 20, 30, 40] 原件一点没变这儿, x 乘以 2 的这种情况便是那道所谓的“加工工序” , map 会将 nums 里面的每一个数, 逐个送去进行这道工序, 10 会变为 20, 20 会变为 40 , 按这样的方式依次变化, 最终整工整齐地交还给你一组全新的数。两个坑新手必踩1. 返回, map生成而是为并非列表所谓迭代器样式之物。直接以print实施操作之时将目睹莫名内存地址呈现情况出现。若愿望查看其中内容, 需记得运用list()进行包裹处理, 或者规规矩矩借助for循环予以遍历方可达成目的。2. 迭代器十分“娇气”, 一旦遍历或者进行 list 转换一回便会用完, 当第二次再进行转换时就会成为空列表。因而要么尽早运用 list() 将结果存入变量, 要么从一开始直接采用 list(map(...)) 一步达成。第二个车间质检筛子承担“挑货”职责: 把一组数据当中合乎条件的筛选找出来, 将不符合心意的舍弃掉。最经典的例子从一堆人里挑出成年人persons [ {name: 张三, age: 15}, {name: 李四, age: 16}, {name: 王五, age: 17}, {name: 李华, age: 18}, {name: 赵六, age: 19}, {name: 孙七, age: 20}, ] adults list(filter(lambda p: p[age] 18, persons)) print(adults) # 只剩李华、赵六、孙七留意, 所书写的是p 18, 并非p 18。p乃是整本“人事档案”字典, 你需要先掀翻档案拿出age这一栏而后再去比较大小, 径直拿整本字典比较必定会报错。另外存在一个偷懒的神奇技巧, 当第一个参数直接传递None时, 它能够自动将“假值”全部筛选掉。data [0, 1, , Hello, [], (), 5] print(list(filter(None, data))) # [1, Hello, 5]0、空着的字符串, 空着的列表, 空着的元组, 转变成布尔值的时候, 都是呈现为False, 会自动被舍弃掉其余的那些具有真值的内容, 全部都留存下来。在清理不干净的数据时, 运用这样的办法, 会格外让人觉得畅快。map以及它和都返回迭代器, 它俩都存在着可能“使用一次就会被耗尽”这种情况而它们之间的区别在于——map不会改变元素数量然而, 却有可能会把数量筛选少。记住这单独的一个要点, 能够减少半小时的调试时间。第三个车间重新排队负责进行排序 并且 它跟前面的那两个存在差异 直接返回的是一个列表 不需要你再次通过list()进行转换 拿到之后就能够直接使用。names [python, go, java] print(sorted(names, keylen)) # [go, java, python] print(sorted(names, keylen, reverseTrue)) # [python, java, go]按字符编码进行的默认排序, 是这样排的由于此原因, go 处于最前面, 然而当添加了 keylen 后, 就转变为按照字符串长度来进行排序。参数 key 所具备的能力, 便是能够让你去指定按照何种方式进行排序。排序字典列表也靠它。比如按年龄给一群人排队print(sorted(persons, keylambda p: p[age])) # 想要从大到小加个 reverseTrue 就行特意提及两位亲戚, max以及min同样能够运用key, 想要寻觅年龄处于最大状态或者最小状态的那个人。print(max(persons, keylambda p: p[age])) # 李华20岁 print(min(persons, keylambda p: p[age])) # 张三15岁单独的一句话, 一旦是涉及到了比大小、挑极值、排顺序这些方面, 那么首先就要去想 / max / min 以及加上 key。第四个车间打包机之前的三个均是“一对多”或者“多对多”这种情况, 与之相反采取这样的做法——把那一堆的数据如同滚雪球一般进行合并, 最终形成一个结果。在生活当中它就类似于把那些散装的零件逐个放进同一个箱子里面, 最后仅仅交给你一个箱子。它比较特殊不能直接用得先从 模块请过来from functools import reduce nums [1, 2, 3, 4, 5] total reduce(lambda a, b: a b, nums) print(total) # 15它这样运行, 逻辑是, 首先抓取前面的两个数, 也就是1和2, 将它们相加而得到3, 接着要把3跟下一个数3相加从而得到6, 之后6再加上4得出10, 然后10加上5得到15。每一回的“和”都会转变成为下一轮的a, 新进来的元素当作b, 一直到队伍全部走完。你还能传第三个参数当初始值print(reduce(lambda a, b: a b, nums, 10)) # 25这回搞的头一遭计算的是十加上一, 这等同于预先朝着箱子里头放置了一件垫底的货物。若进行换行操作, 便可将加号修改成乘号, 随即就会变成求乘积的情况要是将数字替换为字符串, 那就会成为拼接的情形。words [ab, cd, ef] print(reduce(lambda a, b: a b, words)) # abcdef记好了, 给你交予的那个合并函数, 始终都仅仅能够收纳两个参数a以及b, 再多写上哪怕一个, 也不会有人给你去传递的, 直接就会出现报错情况。千万别存有贪心的想法哟。四件套合体记住这张表回头看它们其实对应了数据处理的四种本能动作• 要统一加工 → map• 要挑三拣四 →• 要排排坐 →• 要合并汇总 →又一次拿到那一堆杂乱无章的数据时, 先别急着去写for循环。在心里先过一遍, 我究竟是要进行加工, 还是要进行筛选, 亦或是要进行排序, 又或者是要进行合并呢? 指向对准车间, 将数据送进去, 代码变短了, 思路也变得清爽了。与“返回的‘迭代器’”相关联的“map”究竟是什么东西? 为何那“用一次就没了”呢? 下一篇咱们专门去拆解它。要是觉得有用那就先点个赞收藏起来, 等用到的时候把其翻找出来便可以了。